ContextMenu的Item如何绑定命令
<UserControl x:Class="ATE.View.需求管理View"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:ATE.View"xmlns:i="http://schemas.microsoft.com/xaml/behaviors"xmlns:vm="clr-namespace:ATE.VM"mc:Ignorable="d"FontFamily="Microsoft YaHei"x:Name="root"d:DesignHeight="450" d:DesignWidth="800"><Grid><Grid.ColumnDefinitions><ColumnDefinition Width="*" /><ColumnDefinition Width="auto" /><ColumnDefinition Width="5*" /></Grid.ColumnDefinitions><GroupBox Grid.Column="0"Margin="10"Header="本地数据"><TreeView ItemsSource="{Binding RootNodes}"Tag="{Binding DataContext, ElementName=root}"x:Name="treeView"><TreeView.Resources><!-- 组节点模板 --><HierarchicalDataTemplate DataType="{x:Type vm:GroupNode}"ItemsSource="{Binding Children}"><StackPanel Orientation="Horizontal"x:Name="stackPanel"><Image Source="{Binding Icon}"Width="16"Height="16" /><TextBlock Text="{Binding Name}"Margin="5,0" /><StackPanel.ContextMenu><ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}"><MenuItem Header="添加分组"Command="{Binding AddGroupCommand}"CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu},Path=PlacementTarget.DataContext}" /><MenuItem Header="添加元素"Command="{Binding AddElementCommand}"CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu},Path=PlacementTarget.DataContext}" /><Separator /><MenuItem Header="删除"Command="{Binding DeleteNodeCommand}"CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}, Path=PlacementTarget.DataContext}" /></ContextMenu></StackPanel.ContextMenu></StackPanel></HierarchicalDataTemplate><!-- 元素节点模板 --><DataTemplate DataType="{x:Type vm:ElementNode}"><StackPanel Orientation="Horizontal"Tag="{Binding DataContext, ElementName=root}"><Image Source="{Binding Icon}"Width="16"Height="16" /><TextBlock Text="{Binding Name}"Margin="5,0"FontStyle="Italic" /><StackPanel.ContextMenu><ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}"><MenuItem Header="删除"Command="{Binding DeleteNodeCommand}"CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}, Path=PlacementTarget.DataContext}" /> </ContextMenu></StackPanel.ContextMenu></StackPanel></DataTemplate></TreeView.Resources></TreeView></GroupBox></Grid>
</UserControl>
首先要理解为什么不能直接绑定命令呢
正常情况,我们的控件都是在可视化树上,UserControl继承DataContext,一般都可以直接绑定,如果是一些定制化容器如ListBox,ItemsControl这种就需要用下面这种方法来绑定,但这些都是建立在控件在可视化树上
Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor}, Path=DataContext.EditUserCommand}" CommandParameter="{Binding}"
而ContextMenu属于PopUp控件,不在可视化树上就不能用上述方法
如何绑定不在可视化树上的控件
用控件的tag来中转
上面那个例子,要绑定TreeView中的ContextMenu
首先要让ContextMenu的上层控件的tag来绑定UserControl的DataContext
<UserControl x:Class="ATE.View.需求管理View"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:ATE.View"xmlns:i="http://schemas.microsoft.com/xaml/behaviors"xmlns:vm="clr-namespace:ATE.VM"mc:Ignorable="d"FontFamily="Microsoft YaHei"x:Name="root"d:DesignHeight="450" d:DesignWidth="800">
<StackPanel Orientation="Horizontal"x:Name="stackPanel"Tag="{Binding DataContext, ElementName=root}">
为什么一定要上层控件能,因为ContextMenu里面有一个属性PlacementTarget,他指向的就是上层空间,ContextMenu被StackPanel包裹,所以指向StackPanel
<ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}"><MenuItem Header="删除"Command="{Binding DeleteNodeCommand}"CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}, Path=PlacementTarget.DataContext}" />
</ContextMenu>
一定要用RelativeSource指向自己,如果不这样的话,Wpf会在可视化树中找PlacementTarget属性,很显然是找不到的,这样就可也绑定命令了,只有通过 PlacementTarget.DataContext,才能精确拿到你右键的那个节点。