WPF:菜单项仅绑定命令参数一次

时间:2010-06-10 02:03:29

标签: wpf datagrid menu menuitem commandparameter

我已经注意到这几次使用带命令的菜单时,它们不是很动态,请检查一下。我正在从一组颜色创建一个菜单,我用它来为数据网格中的一个列着色。无论如何,当我第一次调出菜单(它的上下文菜单)时,命令参数绑定发生并且它绑定到打开上下文菜单的列。然而,下次我提起它似乎wpf缓存菜单,它不会重新绑定命令参数。所以我只能在上下文菜单出现的初始列上设置颜色。

我过去已经解决了这种情况,通过使菜单完全动态并在菜单关闭时销毁集合并在下次打开时强制重建,我不喜欢这个黑客。有人有更好的方法吗?

    <MenuItem
       Header="Colour"
       ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:ResultEditorGrid}}, Path=ColumnColourCollection}"
       ItemTemplate="{StaticResource colourHeader}" >
       <MenuItem.Icon>
          <Image
             Source="{StaticResource ColumnShowIcon16}" />
       </MenuItem.Icon>
       <MenuItem.ItemContainerStyle>
          <Style
             TargetType="MenuItem"
             BasedOn="{StaticResource systemMenuItemStyle}">
             <!--Warning dont change the order of the following two setters
                                otherwise the command parameter gets set after the command fires,
                                not mush use eh?-->
             <Setter
                Property="CommandParameter">
                <Setter.Value>
                   <MultiBinding>
                      <MultiBinding.Converter>
                         <local:ColumnAndColourMultiConverter/>
                      </MultiBinding.Converter>
                      <Binding RelativeSource="{RelativeSource AncestorType={x:Type DataGridColumnHeader}}" Path="Column"/>
                      <Binding Path="."/>
                   </MultiBinding>
                </Setter.Value>
             </Setter>
             <Setter
                Property="Command"
                Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:ResultEditorGrid}}, Path=ColourColumnCommand}" />
          </Style>
       </MenuItem.ItemContainerStyle>
    </MenuItem>

1 个答案:

答案 0 :(得分:1)

问题是ContextMenu是apparently the root of their own visual tree我在某处读到了它将datacontext作为其父级,但只在加载时读取一次,因此如果父级datacontext发生更改,则菜单项不会。 (很遗憾,我无法找到相关链接)

之前我遇到过这个问题,我所做的是使用Josh Smith's Virtual Branch Pattern。这是相当技术性的,但这篇文章帮助我理解了这个视觉树无意义的事情。

基本上,您创建了绑定到视图的datacontext的此桥。该桥创建为作为静态资源,允许您从上下文菜单绑定它,即使它位于可视树之外。

将此添加到您的xaml:

<Window.Resources>
   <!-- This is the "root node" in the virtual branch
   attached to the logical tree. It has its
   DataContext set by the Binding applied to the
   Window's DataContext property. -->
   <FrameworkElement x:Key="DataContextBridge" />
</Window.Resources>

<Window.DataContext>
   <!-- This Binding sets the DataContext on the "root node"
   of the virtual logical tree branch.  This Binding
   must be applied to the DataContext of the element
   which is actually assigned the data context value. -->
   <Binding
    Mode="OneWayToSource"
    Path="DataContext"
    Source="{StaticResource DataContextBridge}"
   />
</Window.DataContext>

这是我所说的桥梁。它需要datacontext和__pushes it_到bridge datacontext,这是(如前所述)静态资源。

然后你只需要这个上下文的datacontext:

 DataContext="{Binding
               Source={StaticResource DataContextBridge},
               Path=DataContext}"

现在扔掉所有相对路径等,并在菜单项中使用常规绑定,你应该没问题。 datacontext将照常更新。

只需一个注释:

你显然必须在datacontext中有一些属性来识别要使用的命令,但我相信你可以搞清楚。这个解决方案只涉及contextmenu不更新的方式