3

在使用带有命令的菜单时,我已经多次注意到这一点,它们不是很动态,检查一下。我正在从一组颜色创建一个菜单,我用它来为数据网格中的列着色。无论如何,当我第一次调出菜单(它的上下文菜单)时,命令参数绑定发生并且它绑定到打开上下文菜单的列。但是,下次我提出它时,似乎 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>
4

1 回答 1

1

问题是 ContextMenu显然是他们自己的可视化树的根,我在某处读到它需要它的父级数据上下文,但只有一次加载,所以如果父级数据上下文更改菜单项不会。(不幸的是,我找不到该权利的链接)

我之前遇到过这个问题,我所做的是使用Josh Smith 的 Virtual Branch Pattern。这是相当技术性的,但这篇文章帮助我很好地理解了这个视觉树胡说八道发生了什么。

本质上,您创建了这个绑定到视图数据上下文的桥。桥是作为静态资源创建的,允许您从上下文菜单绑定到它,即使它位于可视树之外。

将此添加到您的 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 和 __pushs it_ 传送到 bridges datacontext,这是(正如我之前所说的)静态资源。

然后,您只需将其添加到上下文菜单的数据上下文中:

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

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

只需注意一点:

您显然必须在 datacontext 中有一些属性来辨别要使用哪个命令,但我相信您可以弄清楚。该解决方案仅处理上下文菜单不更新的方式

于 2012-03-19T11:47:44.687 回答