如何将相同的动态上下文菜单绑定到动态数量的用户控件

本文关键字:动态 控件 用户 绑定 上下文 菜单 | 更新日期: 2023-09-27 18:12:48

想象一下:你有很多控件你想有一个上下文菜单,相同的菜单。该上下文菜单将是动态的,可以随时更改。创建一个静态类,像这样:

public static class EmployeeContextMenu
{
    private static ContextMenu EmployeeMenu { get; set; }
    static EmployeeContextMenu()
    {
        EmployeeMenu = new ContextMenu();
    }
    public static ContextMenu Get()
    {
        return EmployeeMenu;
    }
    public static void Set(List<String> employees)
    {
        EmployeeMenu = new ContextMenu();
        MenuItem mi;
        foreach (var item in employees)
        {
            mi = new MenuItem();
            mi.Header = item;
            EmployeeMenu.Items.Add(mi);
        }
    }
}

在某些时候,您需要更改菜单项并使用上面的Set方法,效果非常好。不知何故,您希望将控件上下文菜单绑定到Get方法。可以这样实现:

<Window.Resources>
    <ObjectDataProvider ObjectType="{x:Type local:EmployeeContextMenu}" MethodName="Get" x:Key="myCM" />
</Window.Resources>
<Grid>
    <TextBlock Name="tb" ContextMenu="{Binding Source={StaticResource myCM}}" />
</Grid>

当然,您希望控件上下文菜单在静态Set方法被调用时立即更新。

但是在上面,绑定基本上是错误的…没有上下文菜单显示。那么如何设置绑定呢?数据源,Datacontext ?在哪里,怎么做?

如果你实现

它当然可以工作
tb.ContextMenu = EmployeeContextMenu.Get();

但这将是一个糟糕的解决方案,如果你有未知数量的动态创建的用户控件,你非常希望有上述的上下文菜单,将在飞行中更新。

如何将相同的动态上下文菜单绑定到动态数量的用户控件

你能做的就是稍微重组一下因为你需要change notification作为EmployeeMenu属性以便在Set()方法之后更新

所以从类本身开始

namespace CSharpWPF
{
    public sealed class EmployeeContextMenu : INotifyPropertyChanged
    {
        private EmployeeContextMenu()
        {
            //prevent init
        }
        static EmployeeContextMenu()
        {
            Instance = new EmployeeContextMenu();
            Instance.EmployeeMenu = new ContextMenu();
        }
        public static EmployeeContextMenu Instance { get; private set; }
        private ContextMenu _menu;
        public ContextMenu EmployeeMenu
        {
            get
            {
                return _menu;
            }
            set
            {
                _menu = value;
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("EmployeeMenu"));
            }
        }
        public void Set(List<String> employees)
        {
            EmployeeMenu = new ContextMenu();
            MenuItem mi;
            foreach (var item in employees)
            {
                mi = new MenuItem();
                mi.Header = item;
                EmployeeMenu.Items.Add(mi);
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
}

我已经实现了INotifyPropertyChanged使用私有构造函数使其非静态以避免初始化密封类以防止进一步派生添加了静态Instance属性来查看xaml

休息是很基本的

xaml

<Grid xmlns:l="clr-namespace:CSharpWPF">
    <TextBlock Name="tb" ContextMenu="{Binding EmployeeMenu,Source={x:Static l:EmployeeContextMenu.Instance}}" />
</Grid>

调用Set()方法

EmployeeContextMenu.Instance.Set(list);

所以整个想法是启用属性更改通知同时保持静态引用