WPF中使用MVVM对ContextMenu绑定Command并通过CommandParameter传递参数

本文介绍如何在MVVM架构下,实现在ListBox的Item上点击右键弹出菜单并绑定Command,解决ContextMenu无法直接访问DataContext的问题,通过在Tag上绑定ViewModel,成功传递选择的ListBoxItem。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需求:
在ListBox中的Item上点击右键时弹出菜单,由于使用MVVM架构,需要把为MenuItem绑定Command,并能把选择的ListBoxItem传递到ViewModel。
实现:
1、只对被点击的ListItem弹出ContextMenu,只需要建立一个DataTemplate即可,这个比较简单。
2、绑定Command,这个是比较麻烦的,查了许多资料,就是利用PlacementTarget来确定ContextMenu的位置,这个方法是正确,但是使用MVVM架构时,由于ContextMenu没有父级节点,不能继承DataContext,所以通过直接设置Command不能找到View所绑定DataContext,从而导致绑定失败。
解决办法是将ViewModel绑定的需要弹出ContextMenu的控件的Tag上,在ContextMenu通过绑定PlacementTarget的Tag来获取ViewModel,然后在设置Command就可以生效了。
3、通过CommandParameter传递选择的ListBoxItem,最开始我用的是PlacementTarget.SelectedItem,但是传到后边的一直是null,调试了好久,突然想明白由于设置的ContextMenu是在附加在DataTemplate中的一个控件上,并不是附加在ListBox上,所以PlacementTarget根本就没有SelectedItem这个属性。而应该使用PlacementTarget.DataContext来获取ContextMenu附着的ListBoxItem。
经过测试可以完美绑定Command并传递选择的Item到后台ViewModel,问题解决!

前台View的DataTemplate代码如下,后台ViewModel比较简单就不贴了,使用的是MVVMLight:

<DataTemplate x:Key="DataTem">
	<StackPanel x:Name="panel" Tag="{Binding Source={StaticResource Locator}, Path=TestVM, Mode=OneWay}">
		<StackPanel.ContextMenu>
			<ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
				<MenuItem Header="菜单项1" Command="{Binding Command1}"
					 CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}, Path=PlacementTarget.DataContext}"/>
				<MenuItem Header="菜单项2" Command="{Binding Command2}"
                     CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}, Path=PlacementTarget.DataContext}"/>
            </ContextMenu>
        </StackPanel.ContextMenu>
        <TextBlock Margin="8" FontSize="16" Text="{Binding Name}"/>
    </StackPanel>
</DataTemplate>

参考了这个帖子:

https://blog.youkuaiyun.com/jumtre/article/details/19540371

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值