Silverlight TabItem Visibility not changing

假装没事ソ 提交于 2019-12-06 05:32:33
Arthur Nunes

I've faced the same problem and I was able to overcome it using a attached "Visibility" property instead the original one. In this new property, I can pass the value to the original "Visibility" property and, in case the parent tab control's "SelectedItem" is being collapsed select the next visible tabItem.

However, as noted here, only that may not be enough if the first item is collapsed when the TabControl loads. This case had to be fixed in the TabControl itself, because tests showed when the fake "Visility" is set for the first time the TabItem does not have access to it's TabControl yet. Because of that I also used a attached property for the TabControl which corrects this issue.

The complete solution:

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

The usage:

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

What if you change the xaml so that you're setting the DataContext first:

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

I'm assuming that Permissions.Inventory is a property on your view model but since you haven't set the context at that point it seems like the binding shouldn't work.

Also, is your converter being hit if you set a breakpoint and if the getter on Permissions.Inventory being called?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!