Silverlight TabControl - 从 TabItem 中的给定控件查找并选择 TabItem

发布于 2024-08-31 05:44:17 字数 286 浏览 9 评论 0原文

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

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

似乎发生的情况是“未选定”选项卡不在可视化树中,因此您无法导航回所属的 TabItem 并将其设为 TabControl 中当前选定的 TabItem。

有谁知道如何做到这一点\实现这一点?

I am building a LOB application that has a main section and a TabControl with various TabItems in it. On hitting save the idea is that any fields in error are highlighted and the first field in error gets the focus.

If the first, and only, field in error is on an Unselected tab the tab should then become selected and the field in error should become highlighted and have focus. But I can not get this to work.

What appears to be happening is that the Unselected tab is not in the visual tree so you can't navigate back to the owning TabItem and make it the currently selected TabItem in the TabControl.

Has anyone got an idea on how this can be done\achieved?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

白馒头 2024-09-07 05:44:17

加载 TabItem:

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

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

仅下面一行不会加载 tabItemOfInterest:

tabControl.SelectedItem = tabItemOfInterest;

但是,我对 David 用来获取错误控件的方法非常感兴趣。

To load the TabItem:

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

This causes the tabItemOfInterest to load alongwith all the contained controls within the TabItem.

The below line alone does not loads the tabItemOfInterest:

tabControl.SelectedItem = tabItemOfInterest;

I would, however, be very interested in the approach David adopted to get to the erroneous control.

柠檬色的秋千 2024-09-07 05:44:17

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

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

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

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

将父级检测更改为使用...

DependencyObjectparent = _Control.Parent;

...而不是使用 VisualTreeHelper。

因此,当您导航层次结构测试时...

if(父级是 TabActivator )
(parent as ITabActivator).Activate( )

...所以当调用Activate时

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

...并且不要忘记您可能有嵌套选项卡,因此您需要继续向上移动层次结构。

How I solved it (by asking the Lead Architect)...

Create an Interface ITabActivator with one method Activate.

Create a class derived from Grid and ITabActivator called TabPageActivator. The constructor of which takes the TabITem and the TabControl.

Instead of adding a simple Grid to the TabItem.Contents add a TabPageActivator.

Change the Parent detection to use...

DependencyObject parent = _Control.Parent;

...instead of using the VisualTreeHelper.

So when you navigate the Hierarchy test for...

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

... so when Activate is called

m_TabControl.SelectedItem = m_TabItem; // From Constructor Parameters.

...and don't forget you may have nested tabs so you need to keep going up the Hierarchy.

離人涙 2024-09-07 05:44:17

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

Extensions 类:

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

I use TabControls for navigation on one of my sites (YinYangMoney) and built a few extension methods that help me to select tabs using Tag names. Here are snippets that should work for you.

The Extensions class:

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

The XAML for your TabControl and TabItems would look something like this:

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

And you can select the Welcome TabItem like so:

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

or

x_TabControl.SelectTab(x_WelcomeTab);
迎风吟唱 2024-09-07 05:44:17

我的解决方案使用附加属性 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();

My solution using attached property TabItem.
Create class 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
}

Next do this on TabControl load event:

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

and this before setting focus:

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();
杀お生予夺 2024-09-07 05:44:17

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

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

I know a way, but it is ugly. It involves using a DispatcherTimer with an interval of a few milliseconds. In Page_Loaded you would start the timer. Then on each tick it sets IsSelected = true for one of the tab items. On the next tick it selects the next tab item etc. until all the tabs have been selected. Then you would have to select the first item again and kill the timer. This will force the visuals in the tab items to load.

You would also have to cover the TabControl with a border or something during this operation. Otherwise the user will see all the tab items quickly flicking past.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文