有一个项目动态加载wpf的菜单控件可以非常有效的做到更具用户权限显示或控制MenuItem菜单,如何实现这种功能,其实也非常简单。
首先需要了解Wpf的menu菜单控件,她的结构其实也非常简单
- <Menu DockPanel.Dock="Top" Name="MenuOptionGroup">
- <MenuItem Header="菜单1">
- <MenuItem Header="内容1">
-
- </MenuItem>
-
- </MenuItem>
- <MenuItem Header="菜单2">
-
- </MenuItem>
- </Menu>

这是其最基本的结构,menu是其菜单主体,menu下面有menuitem,menuitem可以无限的放入menuitem.
具体思路:
获取需要的显示菜单数据(数据需要拥有父id字段,就是这个menitem的上一级menuitem的id),通过先查询出menuitem数据的父id字段为0的menuitem的数据(就是menuitem没有上一级菜单的菜单项目)Add加载menuitem 到menu。然后继续拿到此的id来做查询出是否还有父id的数为此id的,如果有就继续下去,没有则给menuitem 注册一个click事件,用于点击菜单项目做相应的操作。
数据库表设计:

具体实现方法:
- public List<MenuItem> menuItems = new List<MenuItem>();
- public MainIndex()
- {
- InitializeComponent();
- SetMenus();
- foreach ( var item in menuItems)
- {
- MenuOptionGroup.Items.Add(item);
- }
- }
- private void SetMenus()
- {
- List<GblMenu> lstMenus = lstGblMenuItem.Where(t => t.PaterId == 0).ToList();
- foreach (GblMenu item in lstMenus)
- {
- MenuItem menuItem = new MenuItem();
- menuItem.Header = item.MenuName;
- menuItem.Name = item.ItemName;
- menuItem = SetMenuItems(menuItem, item.Id);
- menuItems.Add(menuItem);
- }
- }
- private MenuItem SetMenuItems(MenuItem menuItem, int PatId)
- {
- List<GblMenu> lstMenuItems = lstGblMenuItem.Where(t => t.PaterId == PatId).ToList();
- foreach (GblMenu item in lstMenuItems)
- {
- MenuItem menuItems = new MenuItem();
- menuItems.Header = item.MenuName;
- menuItems.Name = item.ItemName;
-
- menuItem.Items.Add(menuItems);
- if (!lstGblMenuItem.Where(t => t.PaterId == item.Id).ToList().Any())
- {
- menuItems.Click += MenuItems_Click;
- }
- SetMenuItems(menuItems, item.Id);
- }
- return menuItem;
- }
效果:

结语:
其实这只是其中一个方法,且这种方法也适用与Winform,都是同一个套路。
出处:https://blog.csdn.net/weixin_42084199/article/details/95042521
========================================================================
WPF动态创建右键菜单
第一步:菜单接口定义
- public interface IMenuItem
- {
- /// <summary>
- /// 图标
- /// </summary>
- string ImageURL { get; set; }
-
- /// <summary>
- /// 名称
- /// </summary>
- string Caption { get; set; }
-
- /// <summary>
- /// 是否开始分组
- /// </summary>
- bool IsBeginGroup { get; set; }
-
- /// <summary>
- /// 是否可用
- /// </summary>
- bool IsEnable { get; set; }
-
- /// <summary>
- /// 是否可见
- /// </summary>
- bool IsVisible { get; set; }
-
- /// <summary>
- /// 子菜单集合
- /// </summary>
- List<IMenuItem> SubMenus { get; }
-
- /// <summary>
- /// 执行菜单
- /// </summary>
- void ExcuteItem(object OperObj);
- }
第二步:实现菜单接口
- public class MyMeunItem : IMenuItem
- {
- private Action< object> _action;
- public MyMeunItem()
- {
- m_SubMenus = new List<IMenuItem>();
- }
-
- public MyMeunItem(Action<object> action)
- {
- _action = action;
- m_SubMenus = new List<IMenuItem>();
- }
-
- private string m_Caption = "菜单";
- public string Caption
- {
- get
- {
- return m_Caption;
- }
-
- set
- {
- m_Caption = value;
- }
- }
-
- public string ImageURL
- {
- get;
- set;
- }
-
- private bool m_IsBeginGroup;
- public bool IsBeginGroup
- {
- get
- {
- return m_IsBeginGroup;
- }
-
- set
- {
- m_IsBeginGroup = value;
- }
- }
-
- private bool m_IsEnable = true;
- public bool IsEnable
- {
- get
- {
- return m_IsEnable;
- }
-
- set
- {
- m_IsEnable = value;
- }
- }
-
- private bool m_IsVisible = true;
- public bool IsVisible
- {
- get
- {
- return m_IsVisible;
- }
-
- set
- {
- m_IsVisible = value;
- }
- }
-
- private List<IMenuItem> m_SubMenus;
- public List<IMenuItem> SubMenus
- {
- get
- {
- return m_SubMenus;
- }
- }
-
- public void ExcuteItem(object OperObj)
- {
- if (_action != null)
- {
- _action(OperObj);
- }
- else
- {
- MessageBox.Show( "MyMenu Do...");
- }
- }
- }
第三步:自定义控件,添加菜单依赖属性(以button为例)
- public class MyCustomButton : Button
- {
- static MyCustomButton()
- {
- }
-
- public ObservableCollection<IMenuItem> MenuItems
- {
- get { return (ObservableCollection<IMenuItem>)GetValue(MenuItemsProperty); }
- set { SetValue(MenuItemsProperty, value); }
- }
-
- public static readonly DependencyProperty MenuItemsProperty =
- DependencyProperty.Register( "MenuItems",
- typeof(ObservableCollection<IMenuItem>),
- typeof(MyCustomButton),
- new PropertyMetadata( null, new PropertyChangedCallback(MenuItemsChanged)));
-
- private static void MenuItemsChanged(DependencyObject dpObj, DependencyPropertyChangedEventArgs e)
- {
- try
- {
- MyCustomButton dropButton;
- if (dpObj is MyCustomButton)
- dropButton = dpObj as MyCustomButton;
- else
- return;
-
- dropButton.ContextMenu = new ContextMenu();
- ObservableCollection<IMenuItem> colItems = (ObservableCollection<IMenuItem>)dpObj.GetValue(MenuItemsProperty);
- if (colItems == null)
- return;
-
- foreach ( var item in colItems)
- {
- MenuItem menuItem = new MenuItem()
- {
- Header=item.Caption,
- Icon = item.ImageURL,
- IsEnabled = item.IsEnable,
- Visibility = item.IsVisible ? Visibility.Visible : Visibility.Collapsed,
- Tag = item
- };
-
- menuItem.Click += (obj, arg) => ((obj as MenuItem).Tag as IMenuItem).ExcuteItem(obj);
- // 是否开始分组
- if (item.IsBeginGroup)
- {
- dropButton.ContextMenu.Items.Add( new Separator());
- }
-
- dropButton.ContextMenu.Items.Add(menuItem);
- }
-
- dropButton.ContextMenu.PlacementTarget = dropButton;
- dropButton.ContextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
- }
- catch (Exception ex)
- { }
- }
- }
第四步:XAML中添加该自定义按钮
- <Window x:Class="DropDownTest.MainWindow"
- xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x= "http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:d= "http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc= "http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:local= "clr-namespace:DropDownTest"
- xmlns:uc= "clr-namespace:GtMap.Pro.Package.Controls;assembly=GtMap.Pro.Package.Controls"
- mc:Ignorable= "d"
- Title= "MainWindow" Height= "350" Width= "525">
- <Window.DataContext>
- <local:MainFormVM/>
- </Window.DataContext>
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="40"> </RowDefinition>
- <RowDefinition Height="40"> </RowDefinition>
- </Grid.RowDefinitions>
- <uc:MyCustomButton Grid.Row="0" MenuItems="{Binding MenuItems}" Content="下拉按钮" Margin="0" Width="60" Height="20"> </uc:MyCustomButton>
-
- </Grid>
- </Window>
第五步:ViewModel编写,添加菜单项
- public class MainFormVM : INotifyPropertyChanged
- {
- public MainFormVM()
- {
- try
- {
- m_MenuItems = new ObservableCollection<IMenuItem>();
- m_MenuItems.Add( new MyMeunItem() { Caption = "菜单1" });
- var item = new MyMeunItem(MenuFunc) { Caption = "菜单2", IsBeginGroup = true };
- m_MenuItems.Add(item);
- }
- catch
- {
- }
- }
-
- private ObservableCollection<IMenuItem> m_MenuItems;
-
- public event PropertyChangedEventHandler PropertyChanged;
-
- public ObservableCollection<IMenuItem> MenuItems
- {
- get
- {
- return m_MenuItems;
- }
-
- set
- {
- m_MenuItems = value;
- PropertyChanged( this, new PropertyChangedEventArgs( "MenuItems"));
- }
- }
-
-
- public void MenuFunc(object obj)
- {
- MessageBox.Show( "VM VM VM");
- }
- }
-
- public class MyCommand : ICommand
- {
- Action< object> _action;
- public MyCommand(Action<object> action)
- {
- _action = action;
- }
-
- public event EventHandler CanExecuteChanged;
-
- public bool CanExecute(object parameter)
- {
- return true;
- }
-
- public void Execute(object parameter)
- {
- if (_action != null)
- _action(parameter);
- }
- }
界面效果


==
WPF 绑定方式动态创建菜单