WPF ContextMenu 在MVVM模式中绑定 Command及使用CommandParameter传参
ContextMenu无论定义在.cs或.xaml文件中,都不继承父级的DataContext,所以如果要绑定父级的DataContext,直接DataContext=“{Binding}”是行不通的
不能绑父级,但是能绑资源
第一步:定义一个中间类用来做资源对象
1 public class BindingProxy : Freezable 2 { 3 #region Overrides of Freezable 4 5 protected override Freezable CreateInstanceCore() 6 { 7 return new BindingProxy(); 8 } 9 10 #endregion 11 12 public object Data 13 { 14 get { return (object)GetValue(DataProperty); } 15 set { SetValue(DataProperty, value); } 16 } 17 18 public static readonly DependencyProperty DataProperty = 19 DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null)); 20 }
第二步:引用命名空间,在控件中定义资源
1 <UserControl.Resources> 2 <libBinding:BindingProxy x:Key="BindingProxy" Data="{Binding}"/> 3 </UserControl.Resources>
第三步:绑定ContextMenu、MenuItem
(Button.Command 和 ContextMenu.IsOpen 的绑定部分可以不关注,这两个绑定是用来控制ContextMenu打开的)
1 <Button Command="{Binding Customfold}"> 2 <Button.ContextMenu> 3 <ContextMenu DataContext="{Binding Data,Source={StaticResource BindingProxy}}" 4 ItemsSource="{Binding ItemModelCollection}" 5 IsOpen="{Binding OpenCustomfold,Mode=OneWay}"> 6 <ContextMenu.ItemContainerStyle> 7 <Style TargetType="MenuItem"> 8 <Setter Property="Header" Value="{Binding ...}"/> 9 <Setter Property="Command" Value="{Binding ...}"/> 10 <Setter Property="CommandParameter" Value="{Binding ...}"/> 11 </Style> 12 </ContextMenu.ItemContainerStyle> 13 </ContextMenu> 14 </Button.ContextMenu> 15 <Image .../> 16 </Button>
第四步:传递参数
ContextMenu是它自身视觉树的根节点,所以即使通过RelativeSource.FindAncestor也找不到要传递的参数。
解决:可以通过PlacementTarget解决。微软对PlacementTarget的解释是:获取或设置UIElement,当它打开时相对于它确定ContextMenu的位置。应该可以理解为放置此ContextMenu的UIElement。
1 CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}, Path=PlacementTarget}"
如果要传递Item,如ListBox的SelectedItem:
1 CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItem}"
参考:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构