当前位置:首页 > windos > 正文

WPF动态加载Menu菜单

有一个项目动态加载wpf的菜单控件可以非常有效的做到更具用户权限显示或控制MenuItem菜单,如何实现这种功能,其实也非常简单。

  首先需要了解Wpf的menu菜单控件,她的结构其实也非常简单

  1.   <Menu DockPanel.Dock="Top" Name="MenuOptionGroup">
  2.   <MenuItem Header="菜单1">
  3.   <MenuItem Header="内容1">
  4.    
  5.   </MenuItem>
  6.    
  7.   </MenuItem>
  8.   <MenuItem Header="菜单2">
  9.    
  10.   </MenuItem>
  11.   </Menu>

  

这是其最基本的结构,menu是其菜单主体,menu下面有menuitem,menuitem可以无限的放入menuitem.

 

具体思路:

获取需要的显示菜单数据(数据需要拥有父id字段,就是这个menitem的上一级menuitem的id),通过先查询出menuitem数据的父id字段为0的menuitem的数据(就是menuitem没有上一级菜单的菜单项目)Add加载menuitem 到menu。然后继续拿到此的id来做查询出是否还有父id的数为此id的,如果有就继续下去,没有则给menuitem 注册一个click事件,用于点击菜单项目做相应的操作。

 

数据库表设计:

 

具体实现方法:

  1.   public List<MenuItem> menuItems = new List<MenuItem>();
  2.   public MainIndex()
  3.   {
  4.   InitializeComponent();
  5.   SetMenus();
  6.   foreach ( var item in menuItems)
  7.   {
  8.   MenuOptionGroup.Items.Add(item);
  9.   }
  10.   }
  11.   private void SetMenus()
  12.   {
  13.   List<GblMenu> lstMenus = lstGblMenuItem.Where(t => t.PaterId == 0).ToList();
  14.   foreach (GblMenu item in lstMenus)
  15.   {
  16.   MenuItem menuItem = new MenuItem();
  17.   menuItem.Header = item.MenuName;
  18.   menuItem.Name = item.ItemName;
  19.   menuItem = SetMenuItems(menuItem, item.Id);
  20.   menuItems.Add(menuItem);
  21.   }
  22.   }
  23.   private MenuItem SetMenuItems(MenuItem menuItem, int PatId)
  24.   {
  25.   List<GblMenu> lstMenuItems = lstGblMenuItem.Where(t => t.PaterId == PatId).ToList();
  26.   foreach (GblMenu item in lstMenuItems)
  27.   {
  28.   MenuItem menuItems = new MenuItem();
  29.   menuItems.Header = item.MenuName;
  30.   menuItems.Name = item.ItemName;
  31.    
  32.   menuItem.Items.Add(menuItems);
  33.   if (!lstGblMenuItem.Where(t => t.PaterId == item.Id).ToList().Any())
  34.   {
  35.   menuItems.Click += MenuItems_Click;
  36.   }
  37.   SetMenuItems(menuItems, item.Id);
  38.   }
  39.   return menuItem;
  40.   }

效果:

 

结语:

其实这只是其中一个方法,且这种方法也适用与Winform,都是同一个套路。

 

 

出处:https://blog.csdn.net/weixin_42084199/article/details/95042521

========================================================================

WPF动态创建右键菜单

第一步:菜单接口定义

  1.   public interface IMenuItem
  2.   {
  3.   /// <summary>
  4.   /// 图标
  5.   /// </summary>
  6.   string ImageURL { get; set; }
  7.    
  8.   /// <summary>
  9.   /// 名称
  10.   /// </summary>
  11.   string Caption { get; set; }
  12.    
  13.   /// <summary>
  14.   /// 是否开始分组
  15.   /// </summary>
  16.   bool IsBeginGroup { get; set; }
  17.    
  18.   /// <summary>
  19.   /// 是否可用
  20.   /// </summary>
  21.   bool IsEnable { get; set; }
  22.    
  23.   /// <summary>
  24.   /// 是否可见
  25.   /// </summary>
  26.   bool IsVisible { get; set; }
  27.    
  28.   /// <summary>
  29.   /// 子菜单集合
  30.   /// </summary>
  31.   List<IMenuItem> SubMenus { get; }
  32.    
  33.   /// <summary>
  34.   /// 执行菜单
  35.   /// </summary>
  36.   void ExcuteItem(object OperObj);
  37.   }

第二步:实现菜单接口

  1.   public class MyMeunItem : IMenuItem
  2.   {
  3.   private Action< object> _action;
  4.   public MyMeunItem()
  5.   {
  6.   m_SubMenus = new List<IMenuItem>();
  7.   }
  8.    
  9.   public MyMeunItem(Action<object> action)
  10.   {
  11.   _action = action;
  12.   m_SubMenus = new List<IMenuItem>();
  13.   }
  14.    
  15.   private string m_Caption = "菜单";
  16.   public string Caption
  17.   {
  18.   get
  19.   {
  20.   return m_Caption;
  21.   }
  22.    
  23.   set
  24.   {
  25.   m_Caption = value;
  26.   }
  27.   }
  28.    
  29.   public string ImageURL
  30.   {
  31.   get;
  32.   set;
  33.   }
  34.    
  35.   private bool m_IsBeginGroup;
  36.   public bool IsBeginGroup
  37.   {
  38.   get
  39.   {
  40.   return m_IsBeginGroup;
  41.   }
  42.    
  43.   set
  44.   {
  45.   m_IsBeginGroup = value;
  46.   }
  47.   }
  48.    
  49.   private bool m_IsEnable = true;
  50.   public bool IsEnable
  51.   {
  52.   get
  53.   {
  54.   return m_IsEnable;
  55.   }
  56.    
  57.   set
  58.   {
  59.   m_IsEnable = value;
  60.   }
  61.   }
  62.    
  63.   private bool m_IsVisible = true;
  64.   public bool IsVisible
  65.   {
  66.   get
  67.   {
  68.   return m_IsVisible;
  69.   }
  70.    
  71.   set
  72.   {
  73.   m_IsVisible = value;
  74.   }
  75.   }
  76.    
  77.   private List<IMenuItem> m_SubMenus;
  78.   public List<IMenuItem> SubMenus
  79.   {
  80.   get
  81.   {
  82.   return m_SubMenus;
  83.   }
  84.   }
  85.    
  86.   public void ExcuteItem(object OperObj)
  87.   {
  88.   if (_action != null)
  89.   {
  90.   _action(OperObj);
  91.   }
  92.   else
  93.   {
  94.   MessageBox.Show( "MyMenu Do...");
  95.   }
  96.   }
  97.   }

第三步:自定义控件,添加菜单依赖属性(以button为例)

  1.   public class MyCustomButton : Button
  2.   {
  3.   static MyCustomButton()
  4.   {
  5.   }
  6.    
  7.   public ObservableCollection<IMenuItem> MenuItems
  8.   {
  9.   get { return (ObservableCollection<IMenuItem>)GetValue(MenuItemsProperty); }
  10.   set { SetValue(MenuItemsProperty, value); }
  11.   }
  12.    
  13.   public static readonly DependencyProperty MenuItemsProperty =
  14.   DependencyProperty.Register( "MenuItems",
  15.   typeof(ObservableCollection<IMenuItem>),
  16.   typeof(MyCustomButton),
  17.   new PropertyMetadata( null, new PropertyChangedCallback(MenuItemsChanged)));
  18.    
  19.   private static void MenuItemsChanged(DependencyObject dpObj, DependencyPropertyChangedEventArgs e)
  20.   {
  21.   try
  22.   {
  23.   MyCustomButton dropButton;
  24.   if (dpObj is MyCustomButton)
  25.   dropButton = dpObj as MyCustomButton;
  26.   else
  27.   return;
  28.    
  29.   dropButton.ContextMenu = new ContextMenu();
  30.   ObservableCollection<IMenuItem> colItems = (ObservableCollection<IMenuItem>)dpObj.GetValue(MenuItemsProperty);
  31.   if (colItems == null)
  32.   return;
  33.    
  34.   foreach ( var item in colItems)
  35.   {
  36.   MenuItem menuItem = new MenuItem()
  37.   {
  38.   Header=item.Caption,
  39.   Icon = item.ImageURL,
  40.   IsEnabled = item.IsEnable,
  41.   Visibility = item.IsVisible ? Visibility.Visible : Visibility.Collapsed,
  42.   Tag = item
  43.   };
  44.    
  45.   menuItem.Click += (obj, arg) => ((obj as MenuItem).Tag as IMenuItem).ExcuteItem(obj);
  46.   // 是否开始分组
  47.   if (item.IsBeginGroup)
  48.   {
  49.   dropButton.ContextMenu.Items.Add( new Separator());
  50.   }
  51.    
  52.   dropButton.ContextMenu.Items.Add(menuItem);
  53.   }
  54.    
  55.   dropButton.ContextMenu.PlacementTarget = dropButton;
  56.   dropButton.ContextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
  57.   }
  58.   catch (Exception ex)
  59.   { }
  60.   }
  61.   }

第四步:XAML中添加该自定义按钮

  1.   <Window x:Class="DropDownTest.MainWindow"
  2.   xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.   xmlns:x= "http://schemas.microsoft.com/winfx/2006/xaml"
  4.   xmlns:d= "http://schemas.microsoft.com/expression/blend/2008"
  5.   xmlns:mc= "http://schemas.openxmlformats.org/markup-compatibility/2006"
  6.   xmlns:local= "clr-namespace:DropDownTest"
  7.   xmlns:uc= "clr-namespace:GtMap.Pro.Package.Controls;assembly=GtMap.Pro.Package.Controls"
  8.   mc:Ignorable= "d"
  9.   Title= "MainWindow" Height= "350" Width= "525">
  10.   <Window.DataContext>
  11.   <local:MainFormVM/>
  12.   </Window.DataContext>
  13.   <Grid>
  14.   <Grid.RowDefinitions>
  15.   <RowDefinition Height="40"> </RowDefinition>
  16.   <RowDefinition Height="40"> </RowDefinition>
  17.   </Grid.RowDefinitions>
  18.   <uc:MyCustomButton Grid.Row="0" MenuItems="{Binding MenuItems}" Content="下拉按钮" Margin="0" Width="60" Height="20"> </uc:MyCustomButton>
  19.    
  20.   </Grid>
  21.   </Window>

第五步:ViewModel编写,添加菜单项

  1.   public class MainFormVM : INotifyPropertyChanged
  2.   {
  3.   public MainFormVM()
  4.   {
  5.   try
  6.   {
  7.   m_MenuItems = new ObservableCollection<IMenuItem>();
  8.   m_MenuItems.Add( new MyMeunItem() { Caption = "菜单1" });
  9.   var item = new MyMeunItem(MenuFunc) { Caption = "菜单2", IsBeginGroup = true };
  10.   m_MenuItems.Add(item);
  11.   }
  12.   catch
  13.   {
  14.   }
  15.   }
  16.    
  17.   private ObservableCollection<IMenuItem> m_MenuItems;
  18.    
  19.   public event PropertyChangedEventHandler PropertyChanged;
  20.    
  21.   public ObservableCollection<IMenuItem> MenuItems
  22.   {
  23.   get
  24.   {
  25.   return m_MenuItems;
  26.   }
  27.    
  28.   set
  29.   {
  30.   m_MenuItems = value;
  31.   PropertyChanged( this, new PropertyChangedEventArgs( "MenuItems"));
  32.   }
  33.   }
  34.    
  35.    
  36.   public void MenuFunc(object obj)
  37.   {
  38.   MessageBox.Show( "VM VM VM");
  39.   }
  40.   }
  41.    
  42.   public class MyCommand : ICommand
  43.   {
  44.   Action< object> _action;
  45.   public MyCommand(Action<object> action)
  46.   {
  47.   _action = action;
  48.   }
  49.    
  50.   public event EventHandler CanExecuteChanged;
  51.    
  52.   public bool CanExecute(object parameter)
  53.   {
  54.   return true;
  55.   }
  56.    
  57.   public void Execute(object parameter)
  58.   {
  59.   if (_action != null)
  60.   _action(parameter);
  61.   }
  62.   }

界面效果

==

WPF 绑定方式动态创建菜单