在我们的应用程序中,我们有一个中央资源,我们为项目定义所有系统范围的菜单。这些菜单项已绑定到我们对象的系统范围定义的命令。例如,在应用程序中我们处理'Foo'对象的任何地方,我们只需附加'FooContextMenu'资源。效果很好。
但是......其中一个菜单定义了一个表示枚举值的子菜单,因此,我们希望根据对象上枚举类型属性的值来检查适当的菜单项。例如,在显示“Foo”对象的UI中的任何地方,我们都希望显示此上下文菜单...
FooContextMenu
|__First Foo command
|__Set Foo Encoding
| |__EnumValueA
| |__EnumValueB
| |__EnumValueC // <-- Show checkbox if 'Foo.SomeEnumProp' == 'C'
| |__EnumValueD
|__Other Foo command
|__Last Foo command
现在再次说明,由于命令和上下文菜单资源是集中定义的,所以它们都可以很好地执行代码。我们无法弄清楚的是如何在全球范围内处理该复选框。虽然我们可以在任何地方添加“ContextMenuOpening”代码,但这就是问题所在。我们必须在任何地方添加,但我无法想象你必须这样做。
我确定我错过了一些非常明显的东西,因为这是基本的Windows应用程序(实际上是任何操作系统)行为,但我只是看不到它。 (我想知道上下文菜单是否选择了他们附加的项目的数据上下文,我可以做简单的绑定,但这只是猜测。)想法?
答案 0 :(得分:1)
ContextMenu
DataContext
的行为略有不同。
<ContextMenu>
<MenuItem Header="Foo"
Command="{Binding FooCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItems}"/>
</ContextMenu>
DataContext
中MenuItem
的{{1}}将是父级的ContextMenu
,这是ViewModel,它最有可能公开ListBox.ItemsSource
绑定的集合在上面的例子中。
如果您想直接使用在项目列表中表示的模型,您需要使用给定项目的相对路径,如上面CommandParamter
方案中所示。如果您想简单地使用ViewModel公开common命令,那么您可以像以前一样使用绑定,因为DataContext
将是表示项列表的ViewModel。
特定于您的示例,如果您在ViewModel中保持常见行为,则它可能看起来像这样。
<ContextMenu>
<MenuItem Header="Foo">
<CheckBox
Visibility="{Binding Path=YourProperty,
Converter={StaticResource BooleanToVisibilityConverter}}">
My CheckBox
</CheckBox>
</MenuItem>
</ContextMenu>
然后,您可以在ViewModel中调用您的属性,调用一个集中了所有内容的服务。如果您需要模型在转换器中做出决定,则需要使用相对路径将SelectedItem
作为参数传递。