我试图让一个依赖属性列表的内容显示在WPF上下文菜单中。
我有一个具有以下依赖项属性的类,一个Foo列表(数据保持类):
public List<Foo> FooList
{
get { return (List<Foo>)GetValue(FooListProperty); }
set { SetValue(FooListProperty, value); }
}
public static DependencyProperty FooListProperty =
DependencyProperty.Register("FooList", typeof(List<Foo>),
typeof(FooButton));
在XAML中我设置了以下静态资源,我认为它是必需的,因为上下文菜单不是可视化树的一部分:
<UserControl.Resources>
<ResourceDictionary>
<CollectionViewSource
x:Key="FooListSource"
Source="{Binding FooList}"/>
<!-- ... -->
</ResourceDictionary>
</UserControl.Resources>
上面的ResourceDictionary的一部分是一个CompositeCollection,它需要使项目显示在实际的上下文菜单中。如果UserControl CanStop属性为true,我们还会显示分隔符和停止命令。虽然MenuItems本身出现,但这些绑定也会失败。所以,如果我能弄清楚这些失败的原因,List可能会更容易。
<CompositeCollection x:Key="FooListItems">
<CollectionContainer
Collection="{Binding Source={StaticResource FooListSource}}"/>
<Separator
Visibility="{Binding CanStop,
Converter={StaticResource VisibleIfTrue}}" />
<MenuItem
Command="{x:Static Buttons:FooButton.Stop}"
Header="Stop"
Visibility="{Binding CanStop,
Converter={StaticResource VisibleIfTrue}}"/>
</CompositeCollection>
最后是上下文菜单本身,也在ResourceDictionary中:
<ContextMenu
x:Key="FooButtonMenu"
ItemsSource="{Binding Source={StaticResource FooListItems}}"
ItemTemplate="{StaticResource FooListTemplate}"
<ContextMenu.CommandBindings>
<CommandBinding
Command="{x:Static Buttons:FooButton.Stop}"
Executed="Stop_Executed" />
</ContextMenu.CommandBindings>
</ContextMenu>
我觉得我发布了许多代码的方式,但我不确定我是否可以使这篇文章变得更简单。仅显示分隔符和硬编码菜单项。所以必须搞清楚绑定的东西。绑定通常不是那么难,但是现在当我想要绑定一些不属于同一棵树的东西时,我觉得有点迷失。
欢迎任何建议。 :)
答案 0 :(得分:1)
如您所料,您的问题似乎确实是由List<Foo>
代替ObservableCollection<Foo>
造成的。由于List<Foo>
没有通知属性更改,因此让WPF识别您添加或删除项目的唯一方法是暂时将FooList属性设置为其他内容,然后将其重新设置。
无需切换到CLR属性。只需将List<Foo>
更改为ObservableCollection<Foo>
。
CompositeCollection
中的绑定不起作用的原因是CompositeCollection
不是DependencyObject,因此它无法继承DataContext
。
答案 1 :(得分:0)
我不明白为什么你让FooList
成为依赖属性。您不是将其作为绑定的目标,这是创建依赖项属性的最常见原因。您尚未实现回调,因此无法执行更改通知(创建依赖项属性的第二个最常见原因)。您没有将它用于值继承。那么,为什么呢?
在我看来,你真正想要的是FooList
是ObservableCollection<Foo>
类型的普通CLR属性(或任何实现INotifyCollectionChanged
的类)。这将完成您需要的所有更改通知 - 至少,您需要的是您目前发布的代码。