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

时间:2014-07-12 12:16:13

标签: c# wpf dynamic binding contextmenu

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

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,datasource?在哪里以及如何?

如果你实施

,它当然会有用
tb.ContextMenu = EmployeeContextMenu.Get();

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

1 个答案:

答案 0 :(得分:0)

您可以做的是重新构建它,因为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 使用私有构造函数使其非静态以避免init 密封班级以防止进一步推进 添加静态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);

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