Silverlight选项卡项可见性未更改
我有一个TabControl,其中有许多TabItems绑定到一个ViewModel,该ViewModel具有每个TabItem可见性的属性Silverlight选项卡项可见性未更改,silverlight,tabcontrol,visibility,silverlight-5.0,tabitem,Silverlight,Tabcontrol,Visibility,Silverlight 5.0,Tabitem,我有一个TabControl,其中有许多TabItems绑定到一个ViewModel,该ViewModel具有每个TabItem可见性的属性 <sdk:TabControl> <sdk:TabItem Name="Inventory" Header="Inventory" Style="{StaticResource TabItemStyle}" Visibility="{Binding Permissions.Inventory,
<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>
所有选项卡项都默认为折叠的可见性。但是当VM将TabItem更改为Visible时,除非将鼠标移到控件上,否则它不会工作
即使我用一个按钮以编程方式设置可见性,它的行为也是一样的
我已经检查了VM的属性是否正在通知UI,并且它们是否已使用NotifyOnPropertyChanged。如果我把数据绑定到一个按钮的可见性上,它就可以正常工作了……只是TabItems似乎有一个bug
有没有办法让TabItem UI刷新?或者是一个工作环境
谢谢 如果更改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上的getter,是否会命中转换器?我也遇到了同样的问题,我可以使用附加的“可见性”属性而不是原始属性来克服它。在这个新属性中,我可以将该值传递给原始的“可见性”属性,如果父选项卡控件的“SelectedItem”正在折叠,请选择下一个可见选项卡项 但是,如前所述,如果加载TabControl时第一个项已折叠,则仅此可能不够。这种情况必须在TabControl本身中修复,因为测试显示,当第一次设置假“可见性”时,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);
}
}
公共静态类TabControlExtensions
{
///
///在TabControl上使用此属性可更正该行为
///选择折叠选项卡项的方法。
///
///
///
公共静态bool GetSelectOnlyVisibleTab(DependencyObject对象)
{
return(bool)obj.GetValue(SelectOnlyVisibleTabsProperty);
}
公共静态无效设置SelectOnlyVisibleTab(DependencyObject对象,布尔值)
{
对象设置值(仅选择可视选项卡属性、值);
}
公共静态只读从属属性SelectOnlyVisibleTabsProperty=
DependencyProperty.RegisterAttached(“SelectOnlyVisibleTab”、typeof(bool)、typeof(TabControlExtensions)、new PropertyMetadata(false,SelectOnlyVisibleTabsChanged));
public static void SelectOnlyVisibleTabsChanged(对象发送方,DependencyPropertyChangedEventArgs参数)
{
var tabControl=发送方作为tabControl;
if(tabControl==null)返回;
if((bool)args.NewValue)
{
tabControl.SelectionChanged+=tabControl\u SelectionChanged;
正确选择(tabControl);
}
其他的
{
tabControl.SelectionChanged-=tabControl\u SelectionChanged;
}
}
私有静态无效选项卡控件\u SelectionChanged(对象发送方,SelectionChangedEventArgs args)
{
var tabControl=发送方作为tabControl;
if(tabControl==null)返回;
正确选择(tabControl);
}
公共静态无效更正选择(TabControl TabControl)
{
var selected=tabControl.SelectedItem作为UIElement;
if(selected==null)返回;
//如果选定的图元不显示,
//选择下一个可见元素
if(selected.Visibility==System.Windows.Visibility.Collapsed)
tabControl.SelectedItem=tabControl.Items.OfType()
.Where(e=>e.Visibility==System.Windows.Visibility.Visibility)
.FirstOrDefault();
}
}
公共静态类TabItemExtensions
{
///
///在TabItem中使用此属性,而不是在
///更正TabItem可见性更改时TabControl的行为。
///
///
///
公共静态可见性GetVisibility(DependencyObject obj)
{
返回(可见性)对象获取值(可见性属性);
}
公共静态void SetVisibility(DependencyObject对象,可见性值)
{
对象设置值(VisibilityProperty,value);
}
公共静态只读从属属性VisibilityProperty=
DependencyProperty.RegisterAttached(“Visibility”、typeof(Visibility)、typeof(TabItemExtensions)、new PropertyMetadata(Visibility.Visibility、VisibilityChanged));
public static void VisibilityChanged(对象发送方,DependencyPropertyChangedEventArgs参数)
{
var tabItem=发送方作为tabItem;
if(tabItem==null)返回;
变量可见性=(可见性)args.NewValue;
if(tabItem.Visibility==可见性)返回;
tabItem.Visibility=可见性;
if(visibility==visibility.Visible)返回;
//查找选项卡的父选项卡控件并更正选定项,
//如果必要的话。
var tabControl=tabItem.祖先().OfType().FirstOrDefault();
if(tabControl==null)返回;
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>
您使用的SL版本是什么?Permissions属性和Inventory属性的notifying属性是否都已更改?Silverlight 5。两者都是,我检查了更新ViewModel时TabItem是否看到了更改,并且确实看到了。它只是没有更新用户界面。很奇怪!我知道Tab控件中确实有一些bug,如果不亲自查看,我唯一能建议的就是从codeplex下载工具包源代码,并尝试查看Tab控件是否在内部处理Tab项的可见性