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 绑定方式动态创建菜单

原文地址:https://www.cnblogs.com/mq0036/p/12371140.html

时间: 2024-10-09 01:18:01

WPF动态加载Menu菜单的相关文章

WPF动态加载3D&nbsp;放大-旋转-平移

原文:WPF动态加载3D 放大-旋转-平移 WavefrontObjLoader.cs 第二步:ModelVisual3DWithName.cs public class ModelVisual3DWithName:ModelVisual3D { public string Name { get; set; } public object Tag { get; set; } } 第三步:MainWindow.xmal <Grid x:Name="lay"> <View

zTree 从数据库中动态加载树形菜单

这几天做动态菜单用到了这个插件,目前用的很广泛的一个开源框架,最新发布的QUI框架就是用这个插件开发的菜单部分,因此还是很值得深入研究和学习,通过使用感觉功能很丰富,好多函数不用自己开发和编写,官网上有很详尽的API可以参考,用着算顺手但学习使用的过程中也遇到了一些困难,听过反复测试和查资料都理解了,但也在思考一个问题,怎么样才能使得最快的时间从接触一个新东西到灵活掌握的程度? 这个不仅仅是一个树形结构的菜单,每个节点左边可以有一个复选框,看了看也挺简单的,只需要在setting里面配置一个ch

在mvc中动态加载菜单

最近做了一个项目, 要在客户端动态的显示菜单,也就是这些菜单是保存在数据库中的, 在客户端动态加载菜单,这样做的好处很明显,就是菜单很容易修改,直接在后台进行维护,再也不会直接在前面的 视图页面中进行修改,但是,缺点也很明显,实现起来有一定的难度,如果菜单多的话,在前台首次加载时,页面就会变慢,我想谈谈自己在这方面的经验 首先, 我们要创建两个表,(其实一个表也可以了,不过那样的话会变得比较复杂), 一个一级分类表, 一个二级分类表, 两个表的结构如下 : 一个是一级分类表,对应的就是父级菜单,

[WPF学习笔记]动态加载XAML

好久没写Blogs了,现在在看[WPF编程宝典],决定开始重新写博客,和大家一起分享技术. 在编程时我们常希望界面是动态的,可以随时变换而不需要重新编译自己的代码. 以下是动态加载XAML的一个事例代码. 在debug文件夹下新建一个文本文件,重命名为:file.xaml 插入界面代码: <DockPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <Button Name=

WPF 仪表盘 刻度盘 动态 加载中 开源

原文:WPF 仪表盘 刻度盘 动态 加载中 开源 1. 表盘 参数可以设置, codeproject上写的.网址在这里. 源码里有demo,很详细. 源码在这里. 2. 动态Loading 截图效果跟实际有点不一样. 自己把源码写成 资源就好用了呗 地址在这里 3.  有两个类似的                              地址1  地址2 原文地址:https://www.cnblogs.com/lonelyxmas/p/9689224.html

[翻译]-Linux上C++类的动态加载

摘要:本文是翻译文章,主要介绍了运行时重载C++类的技术,包括了Linux上的动态加载接口.C++类的动态加载技术点及实现.自动加载技术等.最后给出了两个应用案例及相关的源代码.   关键字:动态加载,C++类,Linux 原文链接:http://porky.linuxjournal.com:8080/LJ/073/3687.html   推荐: (原文)http://www.tldp.org/HOWTO/text/C++-dlopen (翻译)http://hi.baidu.com/clive

[转] 从 dll 程序集中动态加载窗体

无涯 原文 从 dll 程序集中动态加载窗体 [原创] 昨天晚上花了一晚上时间写了一个从程序集中动态加载窗体的程序.将任何包含窗体的代码编译成 dll 文件,再把 dll 文件拷贝到本程序的目录下,本程序运行时即可动态检查到 dll 文件中的窗体,将窗体类的类型在程序菜单中显示出来,点击菜单即可运行对应的窗体. 本程序主要用到了 Assembly 类动态加载程序集,再得到程序集中包含类的 Type 类型,动态生成类实例,动态调用类方法.个人觉得这是一种提供高度松耦合,可随意扩展的程序结构框架,希

C#中动态加载和卸载DLL

在C++中加载和卸载DLL是一件很容易的事,LoadLibrary和FreeLibrary让你能够轻易的在程序中加载DLL,然后在任何地方 卸载.在C#中我们也能使用Assembly.LoadFile实现动态加载DLL,但是当你试图卸载时,你会很惊讶的发现Assembly没有提供任何 卸载的方法.这是由于托管代码的自动垃圾回收机制会做这件事情,所以C#不提供释放资源的函数,一切由垃圾回收来做.  这引发了一个问题,用Assembly加载的DLL可能只在程序结束的时候才会被释放,这也意味着在程序运

Win8 Metro动态加载内容框架

制作背景 为了参加ImagineCup 2013 世界公民类比赛,我们设计制作了一个可动态扩展的幼教类App.这个App需要能动态加载内容,内容包括带动画可交互的电子书,动画,视频,游戏. 技术支持 2012年10月第一次:因为SVG性能问题,将SVG换为cocos2d-x JSBind,可惜cocos2d-x JSBind不完善,最后换为cocos2d-x html5.11月第二次:cocos2d-x html5性能问题,破产.12月第三次:取消HTML5,转为使用XAML+JS模式. (微软