【问题标题】:Silverlight TabControl - Finding and selecting a TabItem from a given Control in the TabItemSilverlight TabControl - 从 TabItem 中的给定控件中查找和选择 TabItem
【发布时间】:2011-02-14 21:16:37
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: silverlight tabcontrol tabitem


    【解决方案1】:

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

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

    【讨论】:

    • 是的 - 不是一个很好的解决方案。
    • 是的。我自己使用这个解决方案,每次看代码都会让我畏缩。 :) 如果我再做一次,我会把它封装在一个行为中,让它看不见。不幸的是,我想不出另一种方法来渲染视觉效果。
    【解决方案2】:

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

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

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

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

    更改父检测以使用...

    DependencyObject 父级 = _Control.Parent;

    ...而不是使用 VisualTreeHelper。

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

    如果(父级是 TabActivator) (父级为 ITabActivator).Activate( )

    ...所以当调用激活时

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

    ...别忘了你可能有嵌套的标签,所以你需要继续往上走。

    【讨论】:

    • 在显示最终验证选项卡之前,您肯定会首先看到每个选项卡都被选中了吗?
    • 不,它没有,它工作正常。我对解决方案的解释可能有点太简短了。如果您愿意,我可以更详细地解释?
    • small nitpick:我发现在控件上使用非默认构造函数是一个非常糟糕的主意。它使控件对 xaml 不友好...
    【解决方案3】:

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

    扩展类:

    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);
    

    【讨论】:

    • 问题是根据将在其中显示的控件找到要选择的 TabItem。
    【解决方案4】:

    要加载 TabItem:

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

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

    仅以下行不会加载 tabItemOfInterest:

    tabControl.SelectedItem = tabItemOfInterest;
    

    不过,我会对 David 为实现错误控制而采用的方法非常感兴趣。

    【讨论】:

      【解决方案5】:

      我使用附加属性 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();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-21
        • 2014-04-16
        • 1970-01-01
        • 1970-01-01
        • 2010-10-19
        相关资源
        最近更新 更多