如何在外部定义的上下文菜单中绑定子菜单的复选标记?

时间:2011-10-20 16:43:44

标签: c# wpf checkbox contextmenu

在我们的应用程序中,我们有一个中央资源,我们为项目定义所有系统范围的菜单。这些菜单项已绑定到我们对象的系统范围定义的命令。例如,在应用程序中我们处理'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应用程序(实际上是任何操作系统)行为,但我只是看不到它。 (我想知道上下文菜单是否选择了他们附加的项目的数据上下文,我可以做简单的绑定,但这只是猜测。)想法?

1 个答案:

答案 0 :(得分:1)

ContextMenu DataContext的行为略有不同。

<ContextMenu>
      <MenuItem Header="Foo" 
                Command="{Binding FooCommand}" 
                CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItems}"/>
</ContextMenu>

DataContextMenuItem的{​​{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作为参数传递。