代码之家  ›  专栏  ›  技术社区  ›  Aran Mulholland JohnnyAce

wpf:菜单项只绑定一次命令参数

  •  3
  • Aran Mulholland JohnnyAce  · 技术社区  · 15 年前

    我注意到这几次当菜单与命令一起使用时,它们不是非常动态的,检查一下。我正在从一组颜色创建一个菜单,我使用它来为数据报中的一列着色。无论如何,当我第一次打开菜单(它是一个上下文菜单)时,命令参数绑定发生,它绑定到打开上下文菜单的列。但是,下次我打开它时,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 回复  |  直到 13 年前
        1
  •  1
  •   Community CDub    8 年前

    问题是ContextMenu的 apparently the root of their own visual tree 我在某个地方读到它接受它的父级DataContext,但在加载时只接受一次,所以如果父级DataContext更改,则menuitems不会。(不幸的是,我找不到该权利的链接,不是)

    我以前遇到过这个问题,我所做的就是使用 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>
    

    这就是我说的那座桥。它获取数据上下文并将其推送到Bridges数据上下文,这是一个静态资源(如我之前所说)。

    然后,您只需将其发送到ContextMenu的DataContext:

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

    现在,扔掉所有相关的路径等,在菜单项中使用常规绑定,这样就可以了。DataContext将像往常一样更新。

    只有一个音符:

    显然,您必须在dataContext中具有一些属性,才能识别要使用的命令,但我相信您可以找到它。这个解决方案只处理ContextMenu不更新的方式