简体   繁体   English

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

[英]How do you bind the checkmarks of submenus in a context menu defined externally?

In our application we have a central resource where we define all system-wide menus for items. 在我们的应用程序中,我们有一个中央资源,其中我们定义了项目的所有系统级菜单。 These menu items are already bound to system-wide-defined commands for our objects. 这些菜单项已经绑定到对象的系统范围定义的命令中。 For instance, anywhere in the app where we are dealing with a 'Foo' object, we simply attach the 'FooContextMenu' resource. 例如,在应用程序中处理“ Foo”对象的任何地方,我们只需附加“ FooContextMenu”资源。 Works great. 效果很好。

BUT... one of the menus defines a submenu representing enumeration values and as such, we want the apropriate menu item to be checked depending on the value of the enum-typed property on the object. 但是...其中一个菜单定义了代表枚举值的子菜单,因此,我们希望根据对象上枚举类型的属性的值来检查适当的菜单项。 For instance, everywhere in the UI that displays a 'Foo' object, we want to show this context menu... 例如,在用户界面中显示“ Foo”对象的任何地方,我们都希望显示此上下文菜单...

FooContextMenu
    |__First Foo command
    |__Set Foo Encoding
    |   |__EnumValueA
    |   |__EnumValueB
    |   |__EnumValueC // <-- Show checkbox if 'Foo.SomeEnumProp' == 'C'
    |   |__EnumValueD
    |__Other Foo command
    |__Last Foo command

Now again, since the commands and context menu resources are defined centrally, they all work to execute the code just fine. 再一次,由于命令和上下文菜单资源是集中定义的,因此它们都可以很好地执行代码。 What we can't figure out is how to globally deal with that checkbox. 我们无法确定的是如何全局处理该复选框。 While we could add the 'ContextMenuOpening' code everywhere, that's the problem. 尽管我们可以在各处添加“ ContextMenuOpening”代码,但这就是问题所在。 We have to add that everywhere, but I can't imagine that's how you have to do it. 我们必须在所有地方添加它,但是我无法想象这就是您必须这样做的方式。

I'm sure I'm missing something blindingly obvious considering this is basic Windows app (any OS actually) behavior, but I just can't see it. 考虑到这是基本的Windows应用程序行为(实际上是任何操作系统),我肯定会丢失一些令人眼花obvious乱的东西,但是我只是看不到它。 (I'm wondering if the context menus pick up the data context of the item they're attached to and I can do simple bindings, but that's just a guess.) Thoughts? (我想知道上下文菜单是否可以获取它们所附加的项目的数据上下文,并且我可以进行简单的绑定,但这只是一个猜测。)

The ContextMenu behaves a bit differently with regard to the DataContext . ContextMenuDataContext方面的行为有些不同。

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

The DataContext of the MenuItem within the ContextMenu will be that of the parent, which is the ViewModel which most likely exposes the collection which the ListBox.ItemsSource is bound to in the above example. ContextMenu MenuItemDataContext将是父项的DataContext ,后者是ViewModel,最有可能在上面的示例中公开ListBox.ItemsSource绑定到的集合。

If you wanted to work directly with the Model being represented within the listing of items, you would need to use the relative pathing of the given item as seen above in the CommandParamter scenario. 如果要直接使用在项目列表中表示的模型,则需要使用给定项目的相对路径,如上面在CommandParamter方案中所示。 If you want to simply expose the common command with your ViewModel, then you can use the binding as you are used to as the DataContext will be the ViewModel representing the listing of items. 如果只想使用ViewModel公开通用命令,则可以使用绑定,因为DataContext将是表示项目列表的ViewModel。

Specific to your example it could look something like this if you were keeping the common behavior within the ViewModel, versus the Model. 特定于您的示例,如果您在ViewModel和Model之间保留常见行为,则可能看起来像这样。

<ContextMenu>
      <MenuItem Header="Foo">
           <CheckBox 
                 Visibility="{Binding Path=YourProperty, 
                 Converter={StaticResource BooleanToVisibilityConverter}}">
                 My CheckBox
           </CheckBox>
      </MenuItem>
</ContextMenu>

You could then have your property within your ViewModel call out to a Service where you have everything centralized. 然后,您可以将ViewModel内的属性调出到Service,在此您将所有内容集中。 If you need the Model to make your decision within the converter, you will need to use the relative pathing to get the SelectedItem to pass as a parameter. 如果您需要模型来在转换器中做出决定,则需要使用相对路径来获取SelectedItem作为参数传递。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM