6

我正在构建一个 LOB 应用程序,它有一个主要部分和一个包含各种 TabItems 的 TabControl。点击保存的想法是突出显示任何错误的字段,并且错误的第一个字段获得焦点。

如果第一个也是唯一一个错误字段位于未选择选项卡上,则该选项卡应被选中,错误字段应突出显示并具有焦点。但我无法让它发挥作用。

似乎正在发生的事情是 Unselected 选项卡不在可视树中,因此您无法导航回拥有的 TabItem 并使其成为 TabControl 中当前选定的 TabItem。

有没有人知道如何做到这一点?

4

5 回答 5

4

要加载 TabItem:

tabControl.SelectedItem = tabItemOfInterest;
tabControl.UpdateLayout();

这会导致 tabItemOfInterest 与 TabItem 中包含的所有控件一起加载。

仅以下行不会加载 tabItemOfInterest:

tabControl.SelectedItem = tabItemOfInterest;

然而,我会对大卫为实现错误控制而采用的方法非常感兴趣。

于 2011-03-01T18:07:39.920 回答
1

我是如何解决的(通过询问首席架构师)......

使用一种方法激活创建接口 ITabActivator。

创建一个从 Grid 和 ITabActivator 派生的类,称为 TabPageActivator。其构造函数采用 TabITem 和 TabControl。

而不是向 TabItem.Contents 添加一个简单的 Grid,而是添加一个 TabPageActivator。

更改父检测以使用...

DependencyObject 父级 = _Control.Parent;

...而不是使用 VisualTreeHelper。

因此,当您浏览 Hierarchy 测试以...

if ( parent is TabActivator ) (parent as ITabActivator).Activate( )

...所以当调用激活时

m_TabControl.SelectedItem = m_TabItem; // 从构造函数参数。

...并且不要忘记您可能有嵌套的选项卡,因此您需要继续提升层次结构。

于 2010-05-04T04:10:52.683 回答
1

我在我的一个网站 ( YinYangMoney ) 上使用 TabControls 进行导航,并构建了一些扩展方法来帮助我使用标签名称选择标签。以下是适合您的片段。

扩展类:

using System;
using System.Linq;
using System.Windows.Controls;

namespace MyApplication
{
    internal static class Extensions
    {
        // Extension for TabControl
        internal static void SelectTab(this TabControl tabControl, this TabItem tabItem)
        {
            if (tabControl == null || tabItem == null)
                return null;

            SelectTab(tabControl, tabItem.Tag);
        }

        // Extension for TabControl
        internal static void SelectTab(this TabControl tabControl, string tabTagName)
        {
            if (tabControl == null)
                return null;

            // Find the TabItem by its Tag name
            TabItem mainTabItem = tabControl.FindByTag(tabTagName);
            if (mainTabItem == null)
                return;

            // Check to see if the tab needs to be selected
            if (tabControl.SelectedItem != mainTabItem)
                tabControl.SelectedItem = mainTabItem;
        }

        // Extension for TabControl
        internal static TabItem FindByTag(this TabControl tabControl, string tagFragment)
        {
            if (tabControl == null || tagFragment == null)
                return null;

            return tabControl.Items
                    .OfType<TabItem>()
                    .Where(item => item.Tag != null && item.Tag.ToString().StartsWithIgnoreCase(tagFragment))
                    .FirstOrDefault();
        }

        // Extension for string
        internal static bool StartsWithIgnoreCase(this string source, string target)
        {
            return source.StartsWith(target, StringComparison.CurrentCultureIgnoreCase);
        }
    }
}

TabControl 和 TabItems 的 XAML 看起来像这样:

<Controls:TabControl x:Name="x_TabControl">
    <Controls:TabItem Header="Welcome" Tag="/Home/Welcome" x:Name="x_WelcomeTab" />
    <Controls:TabItem Header="FAQ" Tag="/Home/FAQ" />
    <Controls:TabItem Header="Contact Us" Tag="/Home/Contact_Us" />
    <Controls:TabItem Header="Privacy Policy" Tag="/Home/Privacy_Policy" />
    <Controls:TabItem Header="My Account" Tag="/Home/My_Account" />
</Controls:TabControl>

您可以像这样选择 Welcome TabItem:

x_TabControl.SelectTab("/Home/Welcome");  

或者

x_TabControl.SelectTab(x_WelcomeTab);
于 2010-05-04T04:41:17.330 回答
1

我使用附加属性 TabItem 的解决方案。创建类TabItemExtender

/// <summary>
/// TabItem Extender class with TabItem property
/// </summary>
public class TabItemExtender
{
    #region property getters/setters
    /// <summary>
    /// TabItem attached dependency property
    /// </summary>
    public static readonly DependencyProperty TabItemProperty = DependencyProperty.RegisterAttached("TabItem", typeof(TabItem), typeof(TabItemExtender), null);

    /// <summary>
    /// TabItem Property getter
    /// </summary>
    public static TabItem GetNavigateUri(DependencyObject source)
    {
        return (TabItem)source.GetValue(TabItemExtender.TabItemProperty);
    }

    /// <summary>
    /// TabItem Property setter
    /// </summary>
    public static void SetNavigateUri(DependencyObject target, TabItem value)
    {
        target.SetValue(TabItemExtender.TabItemProperty, value);
    }
    #endregion
}

接下来在TabControl加载事件上执行此操作:

private void ExtendedTabControl_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
    foreach (object item in this.Items)
    {
        var tabItem = item as TabItem;
        if (tabItem != null && tabItem.Content != null)
        {
            var element = (FrameworkElement)tabItem.Content;
            element.SetValue(TabItemExtender.TabItemProperty, tabItem);
        }
    }
}

在设置焦点之前:

var element = (UIElement)control;
while (element != null)
{
    //Get TabItem
    var tabItem = (TabItem)element.GetValue(TabItemExtender.TabItemProperty);

    if (tabItem != null)
    {
        if (!tabItem.IsSelected && tabItem.IsEnabled)
        {
            tabItem.IsSelected = true;
            ((TabControl)tabItem.Parent).UpdateLayout();
        }

        break;
    }

    element = (UIElement)VisualTreeHelper.GetParent(element);
}

control.Focus();
于 2012-11-28T18:10:44.747 回答
0

我知道一种方法,但它很难看。它涉及使用间隔为几毫秒的 DispatcherTimer。在 Page_Loaded 中,您将启动计时器。然后在每个刻度上,它为其中一个选项卡项设置 IsSelected = true。在下一个刻度上,它会选择下一个选项卡项目等,直到所有选项卡都被选中。然后您将不得不再次选择第一项并终止计时器。这将强制加载选项卡项中的视觉效果。

在此操作期间,您还必须用边框或其他东西覆盖 TabControl。否则,用户将看到所有选项卡项快速闪过。

于 2010-05-03T10:18:35.493 回答