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打開的)
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}"
參考: