如何在WPF中复用ContextMenu资源并绑定不同命令(非MVVM无后台代码)
问题
希望将ContextMenu保存为XAML资源复用,示例资源如下:
<ContextMenu x:Key="MyMenu"> <MenuItem Header="Add" Icon="..." /> <MenuItem Header="Delete" Icon="..." /> ... </ContextMenu>
并在不同ListView中复用该资源,同时为每个ListView的菜单项绑定不同命令,示例预期用法如下:
<ListView x:Name="Users" ContextMenu="{StaticResource MyMenu}" <ContextMenu.MenuItems(Add).Command = AddUserCommand/> <ContextMenu.MenuItems(Delete).Command = DeleteUserCommand/> ... <ListView x:Name="DataBases" ContextMenu="{StaticResource MyMenu}" <ContextMenu.MenuItems(Add).Command = AddDbCommand/> <ContextMenu.MenuItems(Delete).Command = DeleteDbCommand/>
要求:非MVVM模式、无后台代码实现,此前找到的资源复用方案未解决「为共享ContextMenu的菜单项绑定不同命令」的核心需求。
解决方案
可行,核心思路是利用x:Shared="False"确保每个ListView获取独立的ContextMenu实例,再通过XAML绑定为不同ListView的菜单项关联专属命令,以下是两种实现方式:
方式一:ListView内部定义专属命令资源
定义共享ContextMenu资源
设置x:Shared="False"让每个引用生成新实例,避免命令冲突:<ContextMenu x:Key="MyMenu" x:Shared="False"> <MenuItem Header="Add" Icon="..." Command="{Binding Source={StaticResource CurrentAddCommand}}" /> <MenuItem Header="Delete" Icon="..." Command="{Binding Source={StaticResource CurrentDeleteCommand}}" /> </ContextMenu>在ListView中引用并绑定专属命令
每个ListView内部定义自己的命令资源,ContextMenu实例会自动读取所在ListView的内部资源:<!-- 用户列表 --> <ListView x:Name="Users"> <ListView.Resources> <!-- 替换为你实际的命令实例,如预先定义的RoutedCommand --> <RoutedCommand x:Key="CurrentAddCommand" /> <RoutedCommand x:Key="CurrentDeleteCommand" /> </ListView.Resources> <ListView.ContextMenu> <StaticResource ResourceKey="MyMenu" /> </ListView.ContextMenu> </ListView> <!-- 数据库列表 --> <ListView x:Name="DataBases"> <ListView.Resources> <RoutedCommand x:Key="CurrentAddCommand" /> <RoutedCommand x:Key="CurrentDeleteCommand" /> </ListView.Resources> <ListView.ContextMenu> <StaticResource ResourceKey="MyMenu" /> </ListView.ContextMenu> </ListView>
方式二:利用ListView的Tag属性传递命令
如果不想重复定义命令键名,可以用Tag属性封装命令集合:
定义命令容器类(仅需XAML可实例化的POCO类,无后台逻辑)
<!-- 可放在资源字典或窗口资源中 --> <local:CommandContainer x:Key="UserCommands" AddCommand="{StaticResource AddUserCommand}" DeleteCommand="{StaticResource DeleteUserCommand}" /> <local:CommandContainer x:Key="DbCommands" AddCommand="{StaticResource AddDbCommand}" DeleteCommand="{StaticResource DeleteDbCommand}" />修改共享ContextMenu的绑定
通过RelativeSource获取ListView的Tag属性:<ContextMenu x:Key="MyMenu" x:Shared="False"> <MenuItem Header="Add" Icon="..." Command="{Binding PlacementTarget.Tag.AddCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}" /> <MenuItem Header="Delete" Icon="..." Command="{Binding PlacementTarget.Tag.DeleteCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}" /> </ContextMenu>在ListView中关联命令容器
<ListView x:Name="Users" Tag="{StaticResource UserCommands}" ContextMenu="{StaticResource MyMenu}" /> <ListView x:Name="DataBases" Tag="{StaticResource DbCommands}" ContextMenu="{StaticResource MyMenu}" />
内容的提问来源于stack exchange,提问作者Eugene
相关产品推荐
相关产品推荐

