Silverlight TabControl - поиск и выбор элемента TabItem из заданного элемента управления в элементе TabItem - PullRequest
6 голосов
/ 03 мая 2010

Я создаю LOB-приложение, в котором есть основной раздел и TabControl с различными TabItems. При нажатии кнопки сохранения идея заключается в том, что любые ошибочные поля подсвечиваются, и первое ошибочное поле получает фокус.

Если первое и единственное ошибочное поле находится на невыбранной вкладке, то вкладка должна быть выбрана, а ошибочное поле должно быть выделено и иметь фокус. Но я не могу заставить это работать.

Похоже, происходит то, что вкладка «Не выбрано» находится не в визуальном дереве, поэтому вы не можете вернуться к собственному элементу TabItem и сделать его текущим выбранным элементом TabItem в TabControl.

Кто-нибудь получил представление о том, как это можно сделать \ достичь?

Ответы [ 5 ]

4 голосов
/ 01 марта 2011

Чтобы загрузить TabItem:

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

Это заставляет tabItemOfInterest загружаться вместе со всеми содержащимися в TabItem элементами управления.

Только строка ниже не загружает tabItemOfInterest:

tabControl.SelectedItem = tabItemOfInterest;

Я, однако, был бы очень заинтересован в подходе, принятом Дэвидом, чтобы получить ошибочный контроль.

1 голос
/ 28 ноября 2012

Мое решение с использованием вложенного свойства 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();
1 голос
/ 04 мая 2010

Как я решил (спросив у ведущего архитектора) ...

Создание интерфейса ITabActivator одним методом Activate.

Создайте класс, производный от Grid и ITabActivator, с именем TabPageActivator. Конструктор которого принимает TabITem и TabControl.

Вместо добавления простой сетки в TabItem.Contents добавьте TabPageActivator.

Измените определение родителя, чтобы использовать ...

DependencyObject parent = _Control.Parent;

... вместо использования VisualTreeHelper.

Итак, когда вы переходите к тесту Иерархии для ...

if (родительский объект - TabActivator) (родительский как ITabActivator) .Activate ()

... так что когда активировать называется

m_TabControl.SelectedItem = m_TabItem; // Из параметров конструктора.

... и не забывайте, что у вас могут быть вложенные вкладки, поэтому вам нужно продолжать подниматься по Иерархии.

1 голос
/ 04 мая 2010

Я использую TabControls для навигации по одному из моих сайтов ( YinYangMoney ) и создал несколько методов расширения, которые помогают мне выбирать вкладки, используя имена тегов. Вот фрагменты, которые должны работать на вас.

Класс расширений:

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

XAML для ваших TabControl и TabItems будет выглядеть примерно так:

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

И вы можете выбрать элемент приветствия Tab следующим образом:

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

или

x_TabControl.SelectTab(x_WelcomeTab);
0 голосов
/ 03 мая 2010

Я знаю способ, но он безобразен. Он предполагает использование DispatcherTimer с интервалом в несколько миллисекунд. В Page_Loaded вы бы запустили таймер. Затем на каждом тике он устанавливает IsSelected = true для одного из элементов вкладки. На следующем тике он выбирает следующий элемент вкладки и т. Д., Пока не будут выбраны все вкладки. Тогда вам придется снова выбрать первый элемент и убить таймер. Это заставит визуальные элементы в элементах вкладки загружаться.

Во время этой операции вы также должны накрыть TabControl рамкой или чем-то другим. В противном случае пользователь увидит все элементы вкладки, быстро пролетающие мимо.

...