WPF:菜单项仅绑定命令参数一次
在使用带有命令的菜单时,我已经注意到这一点好几次了,它们不是很动态,请检查一下。我正在从颜色集合创建一个菜单,我用它来为数据网格中的列着色。无论如何,当我第一次调出菜单(它是上下文菜单)时,命令参数绑定就会发生,并且它绑定到打开上下文菜单的列。然而,下次我提出它时,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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是 ContextMenu 的 显然是它们自己的视觉树的根 我在某处读到它将 datacontext 作为其父级,但是仅在加载时一次,因此如果父数据上下文更改,菜单项不会更改。 (不幸的是,我找不到正确的链接)
我以前遇到过这个问题,我所做的是使用 Josh Smith 的虚拟分支模式。这是相当技术性的,但这篇文章帮助我很好地理解了这个视觉树的废话是怎么回事。
本质上,您创建了这个绑定到视图数据上下文的桥。该桥被创建为静态资源,允许您从上下文菜单绑定到它,即使它位于可视化树之外。
将其添加到您的 xaml 中:
这是我谈到的桥梁。它获取数据上下文并将其推送到桥接数据上下文,这是(正如我之前所说的)静态资源。
然后,您只需将其添加到上下文菜单的数据上下文:
现在丢弃所有相对路径等并在菜单项内使用常规绑定,您应该没问题。数据上下文将照常更新。
请注意:
显然,您必须在数据上下文中拥有某些属性才能辨别要使用哪个命令,但我相信您可以弄清楚。该解决方案仅处理上下文菜单不更新的方式
The problem is that ContextMenu's are apparently the root of their own visual tree I read somewhere that it takes the datacontext its parent, but only once on loading, so if the parents datacontext changes the menuitems does not. (unfortunately I can't find a link for that right not)
I have encountered this problem before, and what I did was use Josh Smith's Virtual Branch Pattern. It's fairly technical but the article helped me understand really well what was going on with this visual tree nonsense.
Essentially you create this bridge that binds to the view's datacontext. The bridge is created as a static resource, allowing you to bind to it from the context menu even if it is outside the visual tree.
Add this to your xaml:
This is the bridge I spoke of. It takes the datacontext and __pushes it_ to to the bridges datacontext, which is (as I said before) a static resource.
Then you simply this to the contextmenu's datacontext:
Now throw away all the relative pathing etc and use regular binding inside the menu items, and you should be fine. The datacontext will update as usual.
Just one note:
You will obviously have to have some property in the datacontext to discern which command to use, but i'm sure you can figure it out. This solution just deals with the way contextmenu's dont update