有一個項目動態加載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); } }
界面效果
出處:https://blog.csdn.net/xiangqiang2015/article/details/86219674
=====================================================================================
WPF后台動態生成右鍵菜單
#region 循環生成右鍵菜單 private ContextMenu ContextMenus(Dictionary<string, RoutedEventHandler> list) { ContextMenu cm = new ContextMenu(); Style style = (Style)this.FindResource("ContextMenu"); //定義前台顯示模板 cm.Style = style; foreach (var dc in list) { MenuItem menu = new MenuItem(); menu.Style = (Style)this.FindResource("JjxyMenuItem"); menu.Header = dc.Key; menu.Click += dc.Value; cm.Items.Add(menu); } return cm; } #endregion
需要右鍵菜單的地方使用:
Dictionary<string, RoutedEventHandler> dist = new Dictionary<string, RoutedEventHandler>(); //添加右鍵菜單項,包括名稱和事件 dist.Add("添加", add_Click); dist.Add("修改", edit_Click); dist.Add("刪除", del_Click); dist.Add("導出", putout_Click); dgrid.ContextMenu = ContextMenus(dist);
添加即可,dgrid為DataGrid實例對象,使用字典,string為菜單名,RoutedEventHandler為菜單事件。
出處:https://www.cnblogs.com/qwhh/p/5356091.html
====================================================================================