WPF 中ContextMenu 在mvvm模式中的绑定问题

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打开的) </Button>

 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}"  

原文地址:https://www.cnblogs.com/xietianjiao/p/14545552.html