Silverlight TabItem Видимость не меняется

У меня есть TabControl со многими привязками TabItems к ViewModel, который имеет свойства для видимости каждого TabItem.

<sdk:TabControl>
    <sdk:TabItem Name="Inventory" Header="Inventory" 
        Style="{StaticResource TabItemStyle}"
        Visibility="{Binding Permissions.Inventory,
        Converter={StaticResource PermissiveVisibilityConverter}, 
            ConverterParameter='Viewer'}"
        DataContext="{Binding VM}" />

</sdk:TabControl>

Все TabItems по умолчанию имеют видимость свернутых. Но когда виртуальная машина меняет TabItem на Visible, он не работает, пока вы не наведете указатель мыши на элемент управления...

Даже если я устанавливаю видимость программно с помощью кнопки, она ведет себя так же!

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

Есть ли способ получить интерфейс TabItem для обновления? Или обходной путь для этого?

Спасибо!

2 ответа

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

Однако, как отмечено здесь, только этого может быть недостаточно, если первый элемент свернут при загрузке TabControl. Этот случай должен был быть исправлен в самом TabControl, потому что тесты показали, что когда фальшивая "Visility" установлена ​​впервые, у TabItem еще нет доступа к его TabControl. Из-за этого я также использовал прикрепленное свойство для TabControl, которое исправляет эту проблему.

Полное решение:

public static class TabControlExtensions
{
    /// <summary>
    /// Use this property on a TabControl to correct the behavior
    /// of selecting Collapsed TabItems.
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static bool GetSelectOnlyVisibleTabs(DependencyObject obj)
    {
        return (bool)obj.GetValue(SelectOnlyVisibleTabsProperty);
    }
    public static void SetSelectOnlyVisibleTabs(DependencyObject obj, bool value)
    {
        obj.SetValue(SelectOnlyVisibleTabsProperty, value);
    }
    public static readonly DependencyProperty SelectOnlyVisibleTabsProperty =
        DependencyProperty.RegisterAttached("SelectOnlyVisibleTabs", typeof(bool), typeof(TabControlExtensions), new PropertyMetadata(false, SelectOnlyVisibleTabsChanged));
    public static void SelectOnlyVisibleTabsChanged(object sender, DependencyPropertyChangedEventArgs args)
    {
        var tabControl = sender as TabControl;
        if (tabControl == null) return;

        if ((bool)args.NewValue)
        {
            tabControl.SelectionChanged += TabControl_SelectionChanged;
            CorrectSelection(tabControl);
        }
        else
        {
            tabControl.SelectionChanged -= TabControl_SelectionChanged;
        }
    }

    private static void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs args)
    {
        var tabControl = sender as TabControl;
        if (tabControl == null) return;

        CorrectSelection(tabControl);
    }

    public static void CorrectSelection(TabControl tabControl)
    {
        var selected = tabControl.SelectedItem as UIElement;
        if (selected == null) return;

        // If the selected element is not suposed to be visible,
        // selects the next visible element
        if (selected.Visibility == System.Windows.Visibility.Collapsed)
            tabControl.SelectedItem = tabControl.Items.OfType<UIElement>()
                .Where(e => e.Visibility == System.Windows.Visibility.Visible)
                .FirstOrDefault();
    }
}

public static class TabItemExtensions
{
    /// <summary>
    /// Use this property in a TabItem instead of the original "Visibility" to 
    /// correct the behavior of a TabControl when a TabItem's Visibility changes.
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static Visibility GetVisibility(DependencyObject obj)
    {
        return (Visibility)obj.GetValue(VisibilityProperty);
    }
    public static void SetVisibility(DependencyObject obj, Visibility value)
    {
        obj.SetValue(VisibilityProperty, value);
    }
    public static readonly DependencyProperty VisibilityProperty =
        DependencyProperty.RegisterAttached("Visibility", typeof(Visibility), typeof(TabItemExtensions), new PropertyMetadata(Visibility.Visible, VisibilityChanged));

    public static void VisibilityChanged(object sender, DependencyPropertyChangedEventArgs args)
    {
        var tabItem = sender as TabItem;
        if (tabItem == null) return;

        var visibility = (Visibility)args.NewValue;
        if (tabItem.Visibility == visibility) return;

        tabItem.Visibility = visibility;
        if (visibility == Visibility.Visible) return;

        // Finds the tab's parent tabcontrol and corrects the selected item, 
        // if necessary.
        var tabControl = tabItem.Ancestors().OfType<TabControl>().FirstOrDefault();
        if (tabControl == null) return;

        TabControlExtensions.CorrectSelection(tabControl);
    }
}

Использование:

<sdk:TabControl local:TabControlExtensions.SelectOnlyVisibleTabs="True">
        <sdk:TabItem Header="tabItem1" Visibility="Collapsed">
            <TextBlock HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                       Text="TabItem1 which should not be visible (1)" />
        </sdk:TabItem>
        <sdk:TabItem Header="tabItem2">
            <TextBlock HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                       Text="TabItem2 which should be visible (2)" />
        </sdk:TabItem>
        <sdk:TabItem DataContext="{Binding ViewModel}"
                     Header="tabItem3"
                     local:TabItemExtensions.Visibility="{Binding MyProperty,
                                                                 Converter={StaticResource BoolToVisibilityConverter}}">
            <TextBlock HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                       Text="TabItem with binded Visibility (3)" />
        </sdk:TabItem>
    </sdk:TabControl>

Что если вы измените xaml так, чтобы сначала вы установили DataContext:

 <sdk:TabItem Name="Inventory" Header="Inventory" 
    Style="{StaticResource TabItemStyle}"
    DataContext="{Binding VM}"
    Visibility="{Binding Permissions.Inventory,
    Converter={StaticResource PermissiveVisibilityConverter}, 
        ConverterParameter='Viewer'}" />

Я предполагаю, что Permissions.Inventory является свойством вашей модели представления, но так как вы не установили контекст в этой точке, кажется, что привязка не должна работать.

Кроме того, ваш конвертер подвергается ударам, если вы устанавливаете точку останова и вызывается ли метод получения на Permissions.Inventory?

Другие вопросы по тегам