Silverlight TabItem 可见性不变 [英] Silverlight TabItem Visibility not changing

查看:46
本文介绍了Silverlight TabItem 可见性不变的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 TabControl,其中许多 TabItem 绑定到一个 ViewModel,该 ViewModel 具有每个 TabItem 的可见性的属性.

I have a TabControl with many TabItems binding to a ViewModel that has properties for each TabItem's Visibility.

<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 默认为折叠的可见性.但是,当 VM 将 TabItem 更改为 Visible 时,它​​不会工作,直到您将鼠标移到控件上...

All TabItems are defaulted to a Visibility of collapsed. But when the VM changes a TabItem to Visible it does not work until you move your mouse over the control...

即使我使用按钮以编程方式设置可见性,它的行为也是一样的!

Even if I set the visibility programmatically with a button it behaves the same way!

我已经检查过 VM 的属性是否正在通知 UI,并且它们是否带有 NotifyOnPropertyChanged.如果我将数据绑定到按钮的可见性,它就可以正常工作...只是 TabItems 似乎有错误.

I have checked to see if the VM's properties are Notifying the UI, and they are with NotifyOnPropertyChanged. And if I bind the data to a button's visibility it works just fine...It is just the TabItems that seem to have a bug.

有没有办法让 TabItem UI 刷新?或者解决这个问题?

Is there a way to get the TabItem UI to refresh? Or a work-around for this?

谢谢!

推荐答案

我遇到了同样的问题,我能够使用附加的可见性"属性而不是原始属性来克服它.在这个新属性中,我可以将值传递给原始的可见性"属性,如果父选项卡控件的SelectedItem"被折叠,则选择下一个可见的 tabItem.

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.

但是,如此处所述,仅如果第一项在 TabControl 加载时折叠,这可能还不够.这种情况必须在 TabControl 本身中修复,因为测试显示当第一次设置假的可见性"时,TabItem 还不能访问它的 TabControl.因此,我还使用了 TabControl 的附加属性来纠正这个问题.

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.

完整的解决方案:

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>

这篇关于Silverlight TabItem 可见性不变的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆