我正在尝试将tab的上下文菜单(带复选框)绑定到observable collection。当用户第一次检查或取消选择菜单项时,该状态会反映在中 obesarvable集合中的关联bool变量。但在那之后它没有反映出来。 XAML中的绑定如下所示:
<TabItem.ContextMenu>
<ContextMenu Name="menu"
ItemsSource="{Binding Path=FieldNameCollection,Mode=TwoWay}"
ItemTemplate="{StaticResource SelectIndexFieldMenu}"></ContextMenu>
</TabItem.ContextMenu>
数据模板
<DataTemplate x:Key="SelectIndexFieldMenu">
<MenuItem Header="{Binding Path=IndexFieldName}"
IsCheckable="True"
IsChecked="{Binding Path=isIndexFieldSelected,Mode=TwoWay}"
IsEnabled="{Binding Path=isCheckBoxEnabled}" />
</DataTemplate>
(我无法添加代码段,所以我删除了'&lt;':() 可观察集合的类派生自NotifierBase。 我注意到的另一件事是,如果我在ContextMenuClosing中查看view.xaml.cs中的上下文菜单的itemsource,则会正确反映状态。
答案 0 :(得分:0)
如果没有看到更多代码导致属性不更新的原因尚不清楚,但有一些问题可能会有所帮助。
“isIndexFieldSelected”和“isCheckBoxEnabled”值看起来像字段名而不是属性。如果是这种情况会导致问题,因为Binding需要属性但是给出了发布的代码,它不清楚。
您模板化菜单项的方式将导致为每个集合项创建两个MenuItem对象。 ContextMenu为绑定的ItemsSource集合中的每个项目自动生成一个MenuItem实例,每个项目的DataTemplate将注入其中。通过在ItemTemplate中声明一个MenuItem,您将在ContextMenu中的每个MenuItem的Header部分中创建一个MenuItem。可能是您点击并检查未绑定到数据的外部MenuItem。尝试使用这些资源来模拟和设置为您生成的MenuItem:
<DataTemplate x:Key="SelectIndexFieldMenuTemplate">
<TextBlock Text="{Binding Path=IndexFieldName}"/>
</DataTemplate>
<Style x:Key="SelectIndexFieldMenuStyle" TargetType="{x:Type MenuItem}">
<Setter Property="IsCheckable" Value="True" />
<!--IsChecked is already TwoWay by default-->
<Setter Property="IsChecked" Value="{Binding Path=isIndexFieldSelected}" />
<Setter Property="IsEnabled" Value="{Binding Path=isCheckBoxEnabled}" />
</Style>
并像这样使用它们:
<TabItem.ContextMenu>
<!--TwoWay doesn't ever do anything on ItemsSource-->
<ContextMenu Name="menu" ItemsSource="{Binding Path=FieldNameCollection}"
ItemContainerStyle="{StaticResource SelectIndexFieldMenuStyle}"
ItemTemplate="{StaticResource SelectIndexFieldMenuTemplate}"/>
</TabItem.ContextMenu>
您的绑定属性也可能没有正确使用INotifyPropertyChanged,这会导致UI在菜单项选中状态时不更新。看起来应该是这样的:
private bool _isIndexFieldSelected;
public bool isIndexFieldSelected
{
get { return _isIndexFieldSelected; }
set
{
if (_isIndexFieldSelected == value)
return;
_isIndexFieldSelected = value;
NotifyPropertyChanged("isIndexFieldSelected");
}
}
public virtual void NotifyPropertyChanged(string propertyName)
{
PropertyChangedEventArgs ea = new PropertyChangedEventArgs(propertyName);
if (PropertyChanged != null)
PropertyChanged(this, ea);
}
public event PropertyChangedEventHandler PropertyChanged;