Silverlight TabItem Видимость не меняется - PullRequest
2 голосов
/ 22 марта 2012

У меня есть 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 ]

3 голосов
/ 07 ноября 2012

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

Однако, как отмечено здесь , только этого может быть недостаточно, если первый элемент свернут при загрузке 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>
0 голосов
/ 22 марта 2012

Что если вы измените 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 является свойством вашей модели представления, но поскольку вы не установили контекст в этот момент, кажется, что привязка не должна работать

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

...