ContextMenu无论定义在.cs或.xaml文件中,都不继承父级的DataContext,所以如果要绑定父级的DataContext,直接DataContext=“{Binding}”是行不通的
不能绑父级,但是能绑资源
第一步:定义一个中间类用来做资源对象
1 public class BindingProxy : Freezable
3 #region Overrides of Freezable
5 protected override Freezable CreateInstanceCore()
7 return new BindingProxy();
10 #endregion
12 public object Data
14 get { return (object)GetValue(DataProperty); }
15 set { SetValue(DataProperty, value); }
18 public static readonly DependencyProperty DataProperty =
19 DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
第二步:引用命名空间,在控件中定义资源
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}"