【WPF】ContextMenu 控件

发布时间 2023-04-01 17:58:45作者: 小林野夫

ContextMenu无论定义在.cs或.xaml文件中,都不继承父级的DataContext,所以如果要绑定父级的DataContext,直接DataContext=“{Binding}”是行不通的

不能绑父级,但是能绑资源

 

第一步:定义一个中间类用来做资源对象

public class BindingProxy : Freezable
    {
        #region Overrides of Freezable
 
        protected override Freezable CreateInstanceCore()
        {
            return new BindingProxy();
        }
 
        #endregion
 
        public object Data
        {
            get { return (object)GetValue(DataProperty); }
            set { SetValue(DataProperty, value); }
        }
 
        public static readonly DependencyProperty DataProperty =
            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 Command="{Binding Customfold}">
            <Button.ContextMenu>
                <ContextMenu DataContext="{Binding Data,Source={StaticResource BindingProxy}}"
                             ItemsSource="{Binding ItemModelCollection}"
                             IsOpen="{Binding OpenCustomfold,Mode=OneWay}">
                    <ContextMenu.ItemContainerStyle>
                        <Style TargetType="MenuItem">
                            <Setter Property="Header" Value="{Binding ...}"/>
                            <Setter Property="Command" Value="{Binding ...}"/>
                            <Setter Property="CommandParameter" Value="{Binding ...}"/>
                        </Style>
                    </ContextMenu.ItemContainerStyle>
                </ContextMenu>
            </Button.ContextMenu>
            <Image .../>
        </Button>

第四步:传递参数

ContextMenu是它自身视觉树的根节点,所以即使通过RelativeSource.FindAncestor也找不到要传递的参数。

解决:可以通过PlacementTarget解决。微软对PlacementTarget的解释是:获取或设置UIElement,当它打开时相对于它确定ContextMenu的位置。应该可以理解为放置此ContextMenu的UIElement。

CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}, Path=PlacementTarget}"

如果要传递Item,如ListBox的SelectedItem

CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu},Path=PlacementTarget.SelectedItem}"