zoukankan      html  css  js  c++  java
  • (十三)c#Winform自定义控件-导航菜单-HZHControls

    官网

    http://www.hzhcontrols.com

    前提

    入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。

    GitHub:https://github.com/kwwwvagaa/NetWinformControl

    码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git

    如果觉得写的还行,请点个 star 支持一下吧

    欢迎前来交流探讨: 企鹅群568015492 企鹅群568015492

    目录

    https://www.cnblogs.com/bfyx/p/11364884.html

    准备工作

    有时候我们需要左侧的导航菜单,那么来整一个吧

    先来分析分析,导航菜单一般分为2级或多级,如果是多级的话 用前面的treeview更合适,这里只做2级,为了父子节点样式更方便控制,我们分别实现父子节点。

    为了更加的Open,我们使用接口来定义一下

    开始

    定义一个节点数据绑定实体

     1     [Serializable]
     2     public class MenuItemEntity
     3     {
     4         /// <summary>
     5         /// 6         /// </summary>
     7         public string Key { get; set; }
     8         /// <summary>
     9         /// 文字
    10         /// </summary>
    11         public string Text { get; set; }
    12         /// <summary>
    13         /// 子节点
    14         /// </summary>
    15         public List<MenuItemEntity> Childrens { get; set; }
    16         /// <summary>
    17         /// 自定义数据源,一般用于扩展展示,比如定义节点图片等
    18         /// </summary>
    19         public object DataSource { get; set; }
    20 
    21     }

    再定义一个接口来约束

     1  public interface IMenuItem
     2     {
     3         event EventHandler SelectedItem;
     4         MenuItemEntity DataSource { get; set; }
     5         /// <summary>
     6         /// 设置样式
     7         /// </summary>
     8         /// <param name="styles">key:属性名称,value:属性值</param>
     9         void SetStyle(Dictionary<string, object> styles);
    10         /// <summary>
    11         /// 设置选中样式
    12         /// </summary>
    13         /// <param name="blnSelected">是否选中</param>
    14         void SetSelectedStyle(bool blnSelected);
    15     }

    首先看父节点定义,添加一个用户控件,命名UCMenuParentItem,并且实现接口IMenuItem

      public event EventHandler SelectedItem;
    
            private MenuItemEntity m_dataSource;
            public MenuItemEntity DataSource
            {
                get
                {
                    return m_dataSource;
                }
                set
                {
                    m_dataSource = value;
                    if (value != null)
                    {
                        lblTitle.Text = value.Text;
                    }
                }
            }
     public void SetStyle(Dictionary<string, object> styles)
            {
                Type t = this.GetType();
                foreach (var item in styles)
                {
                    var pro = t.GetProperty(item.Key);
                    if (pro != null && pro.CanWrite)
                    {
                        try
                        {
                            pro.SetValue(this, item.Value, null);
                        }
                        catch (Exception ex)
                        {
                            throw new Exception("菜单元素设置样式异常", ex);
                        }
                    }
                }
            }
    
            public void SetSelectedStyle(bool blnSelected)
            {
                if (blnSelected)
                {
                    this.lblTitle.Image = Properties.Resources.sanjiao1;
                }
                else
                {
                    this.lblTitle.Image = Properties.Resources.sanjiao2;
                }
            }

    然后处理下点击事件

     lblTitle.MouseDown += lblTitle_MouseDown;
    
      void lblTitle_MouseDown(object sender, MouseEventArgs e)
            {
                if (SelectedItem != null)
                {
                    SelectedItem(this, e);
                }
            }

    这样就完事了,看下完整代码

     1 // 版权所有  黄正辉  交流群:568015492   QQ:623128629
     2 // 文件名称:UCMenuParentItem.cs
     3 // 创建日期:2019-08-15 16:02:35
     4 // 功能描述:Menu
     5 // 项目地址:https://gitee.com/kwwwvagaa/net_winform_custom_control
     6 using System;
     7 using System.Collections.Generic;
     8 using System.ComponentModel;
     9 using System.Drawing;
    10 using System.Data;
    11 using System.Linq;
    12 using System.Text;
    13 using System.Windows.Forms;
    14 
    15 namespace HZH_Controls.Controls
    16 {
    17     /// <summary>
    18     /// 父类节点
    19     /// </summary>
    20     [ToolboxItem(false)]
    21     public partial class UCMenuParentItem : UserControl, IMenuItem
    22     {
    23         public event EventHandler SelectedItem;
    24 
    25         private MenuItemEntity m_dataSource;
    26         public MenuItemEntity DataSource
    27         {
    28             get
    29             {
    30                 return m_dataSource;
    31             }
    32             set
    33             {
    34                 m_dataSource = value;
    35                 if (value != null)
    36                 {
    37                     lblTitle.Text = value.Text;
    38                 }
    39             }
    40         }
    41 
    42         public UCMenuParentItem()
    43         {
    44             InitializeComponent();
    45             lblTitle.MouseDown += lblTitle_MouseDown;
    46         }
    47 
    48         public void SetStyle(Dictionary<string, object> styles)
    49         {
    50             Type t = this.GetType();
    51             foreach (var item in styles)
    52             {
    53                 var pro = t.GetProperty(item.Key);
    54                 if (pro != null && pro.CanWrite)
    55                 {
    56                     try
    57                     {
    58                         pro.SetValue(this, item.Value, null);
    59                     }
    60                     catch (Exception ex)
    61                     {
    62                         throw new Exception("菜单元素设置样式异常", ex);
    63                     }
    64                 }
    65             }
    66         }
    67 
    68         public void SetSelectedStyle(bool blnSelected)
    69         {
    70             if (blnSelected)
    71             {
    72                 this.lblTitle.Image = Properties.Resources.sanjiao1;
    73             }
    74             else
    75             {
    76                 this.lblTitle.Image = Properties.Resources.sanjiao2;
    77             }
    78         }
    79 
    80         void lblTitle_MouseDown(object sender, MouseEventArgs e)
    81         {
    82             if (SelectedItem != null)
    83             {
    84                 SelectedItem(this, e);
    85             }
    86         }
    87     }
    88 }
    View Code
     1 namespace HZH_Controls.Controls
     2 {
     3     partial class UCMenuParentItem
     4     {
     5         /// <summary> 
     6         /// 必需的设计器变量。
     7         /// </summary>
     8         private System.ComponentModel.IContainer components = null;
     9 
    10         /// <summary> 
    11         /// 清理所有正在使用的资源。
    12         /// </summary>
    13         /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
    14         protected override void Dispose(bool disposing)
    15         {
    16             if (disposing && (components != null))
    17             {
    18                 components.Dispose();
    19             }
    20             base.Dispose(disposing);
    21         }
    22 
    23         #region 组件设计器生成的代码
    24 
    25         /// <summary> 
    26         /// 设计器支持所需的方法 - 不要
    27         /// 使用代码编辑器修改此方法的内容。
    28         /// </summary>
    29         private void InitializeComponent()
    30         {
    31             this.ucSplitLine_H1 = new HZH_Controls.Controls.UCSplitLine_H();
    32             this.lblTitle = new System.Windows.Forms.Label();
    33             this.SuspendLayout();
    34             // 
    35             // ucSplitLine_H1
    36             // 
    37             this.ucSplitLine_H1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(20)))), ((int)(((byte)(30)))), ((int)(((byte)(39)))));
    38             this.ucSplitLine_H1.Dock = System.Windows.Forms.DockStyle.Bottom;
    39             this.ucSplitLine_H1.Location = new System.Drawing.Point(0, 59);
    40             this.ucSplitLine_H1.Name = "ucSplitLine_H1";
    41             this.ucSplitLine_H1.Size = new System.Drawing.Size(200, 1);
    42             this.ucSplitLine_H1.TabIndex = 0;
    43             this.ucSplitLine_H1.TabStop = false;
    44             // 
    45             // lblTitle
    46             // 
    47             this.lblTitle.Dock = System.Windows.Forms.DockStyle.Fill;
    48             this.lblTitle.ForeColor = System.Drawing.Color.White;
    49             this.lblTitle.Image = global::HZH_Controls.Properties.Resources.sanjiao2;
    50             this.lblTitle.ImageAlign = System.Drawing.ContentAlignment.MiddleRight;
    51             this.lblTitle.Location = new System.Drawing.Point(0, 0);
    52             this.lblTitle.Name = "lblTitle";
    53             this.lblTitle.Size = new System.Drawing.Size(200, 59);
    54             this.lblTitle.TabIndex = 1;
    55             this.lblTitle.Text = "父项";
    56             this.lblTitle.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
    57             // 
    58             // UCMenuParentItem
    59             // 
    60             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
    61             this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(29)))), ((int)(((byte)(43)))), ((int)(((byte)(54)))));
    62             this.Controls.Add(this.lblTitle);
    63             this.Controls.Add(this.ucSplitLine_H1);
    64             this.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
    65             this.Name = "UCMenuParentItem";
    66             this.Size = new System.Drawing.Size(200, 60);
    67             this.ResumeLayout(false);
    68 
    69         }
    70 
    71         #endregion
    72 
    73         private UCSplitLine_H ucSplitLine_H1;
    74         private System.Windows.Forms.Label lblTitle;
    75     }
    76 }
    View Code

    设计效果就是这样子的了

    父节点弄好了,下面就是子节点了

    添加用户控件,命名UCMenuChildrenItem,实现接口IMenuItem

     public event EventHandler SelectedItem;
    
            private MenuItemEntity m_dataSource;
            public MenuItemEntity DataSource
            {
                get
                {
                    return m_dataSource;
                }
                set
                {
                    m_dataSource = value;
                    if (value != null)
                    {
                        lblTitle.Text = value.Text;
                    }
                }
            }
    
     public void SetStyle(Dictionary<string, object> styles)
            {
                Type t = this.GetType();
                foreach (var item in styles)
                {
                    var pro = t.GetProperty(item.Key);
                    if (pro != null && pro.CanWrite)
                    {
                        try
                        {
                            pro.SetValue(this, item.Value, null);
                        }
                        catch (Exception ex)
                        {
                            throw new Exception("菜单元素设置样式异常", ex);
                        }
                    }
                }
            }

    处理下点击事件

    1  this.lblTitle.MouseDown += lblTitle_MouseDown;
    2 
    3        void lblTitle_MouseDown(object sender, MouseEventArgs e)
    4         {
    5             if (SelectedItem != null)
    6             {
    7                 SelectedItem(this, null);
    8             }
    9         }

    这样就完成了,看下完整代码

     1 // 版权所有  黄正辉  交流群:568015492   QQ:623128629
     2 // 文件名称:UCMenuChildrenItem.cs
     3 // 创建日期:2019-08-15 16:02:26
     4 // 功能描述:Menu
     5 // 项目地址:https://gitee.com/kwwwvagaa/net_winform_custom_control
     6 using System;
     7 using System.Collections.Generic;
     8 using System.ComponentModel;
     9 using System.Drawing;
    10 using System.Data;
    11 using System.Linq;
    12 using System.Text;
    13 using System.Windows.Forms;
    14 
    15 namespace HZH_Controls.Controls
    16 {
    17     /// <summary>
    18     /// 子类节点
    19     /// </summary>
    20     [ToolboxItem(false)]
    21     public partial class UCMenuChildrenItem : UserControl, IMenuItem
    22     {
    23         public event EventHandler SelectedItem;
    24 
    25         private MenuItemEntity m_dataSource;
    26         public MenuItemEntity DataSource
    27         {
    28             get
    29             {
    30                 return m_dataSource;
    31             }
    32             set
    33             {
    34                 m_dataSource = value;
    35                 if (value != null)
    36                 {
    37                     lblTitle.Text = value.Text;
    38                 }
    39             }
    40         }
    41         public UCMenuChildrenItem()
    42         {
    43             InitializeComponent();
    44             this.lblTitle.MouseDown += lblTitle_MouseDown;
    45         }
    46 
    47         void lblTitle_MouseDown(object sender, MouseEventArgs e)
    48         {
    49             if (SelectedItem != null)
    50             {
    51                 SelectedItem(this, null);
    52             }
    53         }
    54 
    55         public void SetStyle(Dictionary<string, object> styles)
    56         {
    57             Type t = this.GetType();
    58             foreach (var item in styles)
    59             {
    60                 var pro = t.GetProperty(item.Key);
    61                 if (pro != null && pro.CanWrite)
    62                 {
    63                     try
    64                     {
    65                         pro.SetValue(this, item.Value, null);
    66                     }
    67                     catch (Exception ex)
    68                     {
    69                         throw new Exception("菜单元素设置样式异常", ex);
    70                     }
    71                 }
    72             }
    73         }
    74 
    75         public void SetSelectedStyle(bool blnSelected)
    76         {
    77 
    78         }
    79     }
    80 }
    View Code
     1 namespace HZH_Controls.Controls
     2 {
     3     partial class UCMenuChildrenItem
     4     {
     5         /// <summary> 
     6         /// 必需的设计器变量。
     7         /// </summary>
     8         private System.ComponentModel.IContainer components = null;
     9 
    10         /// <summary> 
    11         /// 清理所有正在使用的资源。
    12         /// </summary>
    13         /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
    14         protected override void Dispose(bool disposing)
    15         {
    16             if (disposing && (components != null))
    17             {
    18                 components.Dispose();
    19             }
    20             base.Dispose(disposing);
    21         }
    22 
    23         #region 组件设计器生成的代码
    24 
    25         /// <summary> 
    26         /// 设计器支持所需的方法 - 不要
    27         /// 使用代码编辑器修改此方法的内容。
    28         /// </summary>
    29         private void InitializeComponent()
    30         {
    31             this.ucSplitLine_H1 = new HZH_Controls.Controls.UCSplitLine_H();
    32             this.lblTitle = new System.Windows.Forms.Label();
    33             this.SuspendLayout();
    34             // 
    35             // ucSplitLine_H1
    36             // 
    37             this.ucSplitLine_H1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(29)))), ((int)(((byte)(43)))), ((int)(((byte)(54)))));
    38             this.ucSplitLine_H1.Dock = System.Windows.Forms.DockStyle.Bottom;
    39             this.ucSplitLine_H1.Location = new System.Drawing.Point(0, 59);
    40             this.ucSplitLine_H1.Name = "ucSplitLine_H1";
    41             this.ucSplitLine_H1.Size = new System.Drawing.Size(200, 1);
    42             this.ucSplitLine_H1.TabIndex = 0;
    43             this.ucSplitLine_H1.TabStop = false;
    44             // 
    45             // lblTitle
    46             // 
    47             this.lblTitle.Dock = System.Windows.Forms.DockStyle.Fill;
    48             this.lblTitle.Font = new System.Drawing.Font("微软雅黑", 12F);
    49             this.lblTitle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(145)))), ((int)(((byte)(152)))), ((int)(((byte)(170)))));
    50             this.lblTitle.Location = new System.Drawing.Point(0, 0);
    51             this.lblTitle.Name = "lblTitle";
    52             this.lblTitle.Size = new System.Drawing.Size(200, 59);
    53             this.lblTitle.TabIndex = 1;
    54             this.lblTitle.Text = "子项";
    55             this.lblTitle.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
    56             // 
    57             // UCMenuChildrenItem
    58             // 
    59             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
    60             this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(20)))), ((int)(((byte)(30)))), ((int)(((byte)(39)))));
    61             this.Controls.Add(this.lblTitle);
    62             this.Controls.Add(this.ucSplitLine_H1);
    63             this.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
    64             this.Name = "UCMenuChildrenItem";
    65             this.Size = new System.Drawing.Size(200, 60);
    66             this.ResumeLayout(false);
    67 
    68         }
    69 
    70         #endregion
    71 
    72         private UCSplitLine_H ucSplitLine_H1;
    73         private System.Windows.Forms.Label lblTitle;
    74 
    75     }
    76 }
    View Code

    设计效果是这样子的

    你们有没有发现,父节点和子节点代码非常的相似呢?是的,基本上都是一样的,他们都实现了接口IMenuItem,

    那既然如此为什么还要分为2个,这不是代码冗余了吗?这么做的好处就是你可以更方便的控制节点的设计样式,假如有一天,子节点你不想用文字了,你先够用图片呢?

     到此,节点定义已经完成了,剩下的就是处理列表了,继续往下看吧。

    定义一个用户控件,命名UCMenu

    首先定义一个枚举

    public enum MenuStyle
        {
            /// <summary>
            /// 平铺
            /// </summary>
            Fill = 1,
            /// <summary>
            /// 顶部对齐
            /// </summary>
            Top = 2,
        }

    这个枚举的作用就是改变样式,默认是Fill,也就是子节点面板填充铺满,选中父节点上面的兄弟节点顶端对齐,下面的兄弟节点低端对齐,当父节点较多时候就会出现子节点无法显示的问题,这个时候使用Top就可以了,所有父节点顶端对齐

    先看下有哪些属性

     1  /// <summary>
     2         /// 选中项事件
     3         /// </summary>
     4         public event EventHandler SelectedItem;
     5         private Type m_parentItemType = typeof(UCMenuParentItem);
     6         /// <summary>
     7         /// 父类节点类型
     8         /// </summary>
     9         public Type ParentItemType
    10         {
    11             get { return m_parentItemType; }
    12             set
    13             {
    14                 if (value == null)
    15                     return;
    16                 if (!typeof(IMenuItem).IsAssignableFrom(value) || !value.IsSubclassOf(typeof(Control)))
    17                     throw new Exception("节点控件没有实现IMenuItem接口");
    18                 m_parentItemType = value;
    19 
    20             }
    21         }
    22 
    23         private Type m_childrenItemType = typeof(UCMenuChildrenItem);
    24         /// <summary>
    25         /// 子类节点类型
    26         /// </summary>
    27         public Type ChildrenItemType
    28         {
    29             get { return m_childrenItemType; }
    30             set
    31             {
    32                 if (value == null)
    33                     return;
    34                 if (!typeof(IMenuItem).IsAssignableFrom(value) || !value.IsSubclassOf(typeof(Control)))
    35                     throw new Exception("节点控件没有实现IMenuItem接口");
    36                 m_childrenItemType = value;
    37             }
    38         }
    39 
    40         private Dictionary<string, object> m_parentItemStyles;
    41         /// <summary>
    42         /// 父类节点样式设置,key:属性名称,value:属性值
    43         /// </summary>
    44         public Dictionary<string, object> ParentItemStyles
    45         {
    46             get { return m_parentItemStyles; }
    47             set { m_parentItemStyles = value; }
    48         }
    49 
    50         private Dictionary<string, object> m_childrenItemStyles;
    51         /// <summary>
    52         /// 子类节点样式设置,key:属性名称,value:属性值
    53         /// </summary>
    54         public Dictionary<string, object> ChildrenItemStyles
    55         {
    56             get { return m_childrenItemStyles; }
    57             set { m_childrenItemStyles = value; }
    58         }
    59 
    60         private List<MenuItemEntity> m_dataSource;
    61         /// <summary>
    62         /// 数据源
    63         /// </summary>
    64         public List<MenuItemEntity> DataSource
    65         {
    66             get { return m_dataSource; }
    67             set
    68             {
    69                 m_dataSource = value;
    70 
    71                 ReloadItems();
    72             }
    73         }
    74         private bool m_isShowFirstItem = true;
    75         /// <summary>
    76         /// 是否自动展开第一个节点
    77         /// </summary>
    78         public bool IsShowFirstItem
    79         {
    80             get { return m_isShowFirstItem; }
    81             set { m_isShowFirstItem = value; }
    82         }
    83 
    84         private MenuStyle m_menuStyle = MenuStyle.Fill;
    85         /// <summary>
    86         /// 菜单样式
    87         /// </summary>
    88         public MenuStyle MenuStyle
    89         {
    90             get { return m_menuStyle; }
    91             set { m_menuStyle = value; }
    92         }
    93 
    94         private List<Control> m_lstParentItems = new List<Control>();
    95 
    96         private IMenuItem m_selectParentItem = null;
    97         private IMenuItem m_selectChildrenItem = null;
    98 
    99         private Panel m_panChildren = null;

    数据源改变时需要重新加载

     1 private void ReloadItems()
     2         {
     3             try
     4             {
     5                 ControlHelper.FreezeControl(this, true);
     6                 this.Controls.Clear();
     7                 m_lstParentItems.Clear();
     8                 if (m_dataSource != null && m_dataSource.Count > 0)
     9                 {
    10                     foreach (var parent in m_dataSource)
    11                     {
    12                         IMenuItem parentItem = (IMenuItem)Activator.CreateInstance(m_parentItemType);
    13                         parentItem.DataSource = parent;
    14                         if (m_parentItemStyles != null)
    15                             parentItem.SetStyle(m_parentItemStyles);
    16                         parentItem.SelectedItem += parentItem_SelectedItem;
    17                         Control c = parentItem as Control;
    18                         c.Dock = DockStyle.Top;
    19                         this.Controls.Add(c);
    20                         this.Controls.SetChildIndex(c, 0);
    21                         m_lstParentItems.Add(c);
    22                     }
    23                 }
    24                 m_panChildren = new Panel();
    25                 if (m_menuStyle == HZH_Controls.Controls.MenuStyle.Fill)
    26                 {
    27                     m_panChildren.Dock = DockStyle.Fill;
    28                     m_panChildren.Height = 0;
    29                 }
    30                 else
    31                 {
    32                     m_panChildren.Dock = DockStyle.Top;
    33                     m_panChildren.Height = 0;
    34                 }
    35                 m_panChildren.AutoScroll = true;
    36                 this.Controls.Add(m_panChildren);
    37             }
    38             finally
    39             {
    40                 ControlHelper.FreezeControl(this, false);
    41             }
    42 
    43             if (m_isShowFirstItem && m_lstParentItems != null && m_lstParentItems.Count > 0)
    44             {
    45                 parentItem_SelectedItem(m_lstParentItems[0], null);
    46             }
    47         }

    选中父节点时候加载子节点

      1  void parentItem_SelectedItem(object sender, EventArgs e)
      2         {
      3             this.FindForm().ActiveControl = this;
      4             IMenuItem item = sender as IMenuItem;
      5             if (m_lstParentItems.Contains(sender as Control))
      6             {
      7                 if (m_selectParentItem != item)
      8                 {
      9                     if (m_selectParentItem != null)
     10                     {
     11                         m_selectParentItem.SetSelectedStyle(false);
     12                     }
     13                     m_selectParentItem = item;
     14                     m_selectParentItem.SetSelectedStyle(true);
     15                     SetChildrenControl(m_selectParentItem);
     16                 }
     17                 else
     18                 {
     19                     m_selectParentItem.SetSelectedStyle(false);
     20                     m_selectParentItem = null;
     21                     SetChildrenControl(m_selectParentItem, false);
     22                 }
     23             }
     24             else if (m_panChildren.Controls.Contains(sender as Control))
     25             {
     26                 if (m_selectChildrenItem != item)
     27                 {
     28                     if (m_selectChildrenItem != null)
     29                     {
     30                         m_selectChildrenItem.SetSelectedStyle(false);
     31                     }
     32                     m_selectChildrenItem = item;
     33                     m_selectChildrenItem.SetSelectedStyle(true);
     34                 }
     35             }
     36             if (SelectedItem != null)
     37             {
     38                 SelectedItem(sender, e);
     39             }
     40         }
     41 
     42         private void SetChildrenControl(IMenuItem menuitem, bool blnChildren = true)
     43         {
     44             try
     45             {
     46                 ControlHelper.FreezeControl(this, true);
     47                 if (m_menuStyle == HZH_Controls.Controls.MenuStyle.Fill)
     48                 {
     49                     if (blnChildren)
     50                     {
     51                         Control cMenu = menuitem as Control;
     52                         int index = m_lstParentItems.IndexOf(cMenu);
     53                         for (int i = 0; i <= index; i++)
     54                         {
     55                             m_lstParentItems[i].Dock = DockStyle.Top;
     56                             this.Controls.SetChildIndex(m_lstParentItems[i], 1);
     57                         }
     58                         for (int i = index + 1; i < m_lstParentItems.Count; i++)
     59                         {
     60                             m_lstParentItems[i].Dock = DockStyle.Bottom;
     61                             this.Controls.SetChildIndex(m_lstParentItems[i], m_lstParentItems.Count);
     62                         }
     63                         m_panChildren.Controls.Clear();
     64                         int intItemHeigth = 0;
     65                         foreach (var item in menuitem.DataSource.Childrens)
     66                         {
     67                             IMenuItem parentItem = (IMenuItem)Activator.CreateInstance(m_childrenItemType);
     68                             parentItem.DataSource = item;
     69                             if (m_childrenItemStyles != null)
     70                                 parentItem.SetStyle(m_childrenItemStyles);
     71                             parentItem.SelectedItem += parentItem_SelectedItem;
     72                             Control c = parentItem as Control;
     73                             if (intItemHeigth == 0)
     74                                 intItemHeigth = c.Height;
     75                             c.Dock = DockStyle.Top;
     76                             m_panChildren.Controls.Add(c);
     77                             m_panChildren.Controls.SetChildIndex(c, 0);
     78                         }
     79                         //m_panChildren.MinimumSize = new Size(0, menuitem.DataSource.Childrens.Count * intItemHeigth);
     80                     }
     81                     else
     82                     {
     83                         m_panChildren.Controls.Clear();
     84                         foreach (var item in m_lstParentItems)
     85                         {
     86                             item.Dock = DockStyle.Top;
     87                             this.Controls.SetChildIndex(item, 1);
     88                         }
     89                     }
     90                 }
     91                 else
     92                 {
     93                     if (blnChildren)
     94                     {
     95                         Control cMenu = menuitem as Control;
     96                         int index = m_lstParentItems.IndexOf(cMenu);
     97                         this.Controls.SetChildIndex(m_panChildren, m_lstParentItems.Count - index - 1);
     98                         m_panChildren.Controls.Clear();
     99                         int intItemHeigth = 0;
    100                         foreach (var item in menuitem.DataSource.Childrens)
    101                         {
    102                             IMenuItem parentItem = (IMenuItem)Activator.CreateInstance(m_childrenItemType);
    103                             parentItem.DataSource = item;
    104                             if (m_childrenItemStyles != null)
    105                                 parentItem.SetStyle(m_childrenItemStyles);
    106                             parentItem.SelectedItem += parentItem_SelectedItem;
    107                             Control c = parentItem as Control;
    108                             if (intItemHeigth == 0)
    109                                 intItemHeigth = c.Height;
    110                             c.Dock = DockStyle.Top;
    111                             m_panChildren.Controls.Add(c);
    112                             m_panChildren.Controls.SetChildIndex(c, 0);
    113                         }
    114                         m_panChildren.Height = menuitem.DataSource.Childrens.Count * intItemHeigth;
    115                     }
    116                     else
    117                     {
    118                         m_panChildren.Controls.Clear();
    119                         m_panChildren.Height = 0;
    120                     }
    121                 }
    122             }
    123             finally
    124             {
    125                 ControlHelper.FreezeControl(this, false);
    126             }
    127         }

    代码就这么多,看下完整代码

      1 // 版权所有  黄正辉  交流群:568015492   QQ:623128629
      2 // 文件名称:UCMenu.cs
      3 // 创建日期:2019-08-15 16:02:22
      4 // 功能描述:Menu
      5 // 项目地址:https://gitee.com/kwwwvagaa/net_winform_custom_control
      6 using System;
      7 using System.Collections.Generic;
      8 using System.ComponentModel;
      9 using System.Drawing;
     10 using System.Data;
     11 using System.Linq;
     12 using System.Text;
     13 using System.Windows.Forms;
     14 
     15 namespace HZH_Controls.Controls
     16 {
     17     public partial class UCMenu : UserControl
     18     {
     19         /// <summary>
     20         /// 选中项事件
     21         /// </summary>
     22         public event EventHandler SelectedItem;
     23         private Type m_parentItemType = typeof(UCMenuParentItem);
     24         /// <summary>
     25         /// 父类节点类型
     26         /// </summary>
     27         public Type ParentItemType
     28         {
     29             get { return m_parentItemType; }
     30             set
     31             {
     32                 if (value == null)
     33                     return;
     34                 if (!typeof(IMenuItem).IsAssignableFrom(value) || !value.IsSubclassOf(typeof(Control)))
     35                     throw new Exception("节点控件没有实现IMenuItem接口");
     36                 m_parentItemType = value;
     37 
     38             }
     39         }
     40 
     41         private Type m_childrenItemType = typeof(UCMenuChildrenItem);
     42         /// <summary>
     43         /// 子类节点类型
     44         /// </summary>
     45         public Type ChildrenItemType
     46         {
     47             get { return m_childrenItemType; }
     48             set
     49             {
     50                 if (value == null)
     51                     return;
     52                 if (!typeof(IMenuItem).IsAssignableFrom(value) || !value.IsSubclassOf(typeof(Control)))
     53                     throw new Exception("节点控件没有实现IMenuItem接口");
     54                 m_childrenItemType = value;
     55             }
     56         }
     57 
     58         private Dictionary<string, object> m_parentItemStyles;
     59         /// <summary>
     60         /// 父类节点样式设置,key:属性名称,value:属性值
     61         /// </summary>
     62         public Dictionary<string, object> ParentItemStyles
     63         {
     64             get { return m_parentItemStyles; }
     65             set { m_parentItemStyles = value; }
     66         }
     67 
     68         private Dictionary<string, object> m_childrenItemStyles;
     69         /// <summary>
     70         /// 子类节点样式设置,key:属性名称,value:属性值
     71         /// </summary>
     72         public Dictionary<string, object> ChildrenItemStyles
     73         {
     74             get { return m_childrenItemStyles; }
     75             set { m_childrenItemStyles = value; }
     76         }
     77 
     78         private List<MenuItemEntity> m_dataSource;
     79         /// <summary>
     80         /// 数据源
     81         /// </summary>
     82         public List<MenuItemEntity> DataSource
     83         {
     84             get { return m_dataSource; }
     85             set
     86             {
     87                 m_dataSource = value;
     88 
     89                 ReloadItems();
     90             }
     91         }
     92         private bool m_isShowFirstItem = true;
     93         /// <summary>
     94         /// 是否自动展开第一个节点
     95         /// </summary>
     96         public bool IsShowFirstItem
     97         {
     98             get { return m_isShowFirstItem; }
     99             set { m_isShowFirstItem = value; }
    100         }
    101 
    102         private MenuStyle m_menuStyle = MenuStyle.Fill;
    103         /// <summary>
    104         /// 菜单样式
    105         /// </summary>
    106         public MenuStyle MenuStyle
    107         {
    108             get { return m_menuStyle; }
    109             set { m_menuStyle = value; }
    110         }
    111 
    112         private List<Control> m_lstParentItems = new List<Control>();
    113 
    114         private IMenuItem m_selectParentItem = null;
    115         private IMenuItem m_selectChildrenItem = null;
    116 
    117         private Panel m_panChildren = null;
    118 
    119         private void ReloadItems()
    120         {
    121             try
    122             {
    123                 ControlHelper.FreezeControl(this, true);
    124                 this.Controls.Clear();
    125                 m_lstParentItems.Clear();
    126                 if (m_dataSource != null && m_dataSource.Count > 0)
    127                 {
    128                     foreach (var parent in m_dataSource)
    129                     {
    130                         IMenuItem parentItem = (IMenuItem)Activator.CreateInstance(m_parentItemType);
    131                         parentItem.DataSource = parent;
    132                         if (m_parentItemStyles != null)
    133                             parentItem.SetStyle(m_parentItemStyles);
    134                         parentItem.SelectedItem += parentItem_SelectedItem;
    135                         Control c = parentItem as Control;
    136                         c.Dock = DockStyle.Top;
    137                         this.Controls.Add(c);
    138                         this.Controls.SetChildIndex(c, 0);
    139                         m_lstParentItems.Add(c);
    140                     }
    141                 }
    142                 m_panChildren = new Panel();
    143                 if (m_menuStyle == HZH_Controls.Controls.MenuStyle.Fill)
    144                 {
    145                     m_panChildren.Dock = DockStyle.Fill;
    146                     m_panChildren.Height = 0;
    147                 }
    148                 else
    149                 {
    150                     m_panChildren.Dock = DockStyle.Top;
    151                     m_panChildren.Height = 0;
    152                 }
    153                 m_panChildren.AutoScroll = true;
    154                 this.Controls.Add(m_panChildren);
    155             }
    156             finally
    157             {
    158                 ControlHelper.FreezeControl(this, false);
    159             }
    160 
    161             if (m_isShowFirstItem && m_lstParentItems != null && m_lstParentItems.Count > 0)
    162             {
    163                 parentItem_SelectedItem(m_lstParentItems[0], null);
    164             }
    165         }
    166 
    167         void parentItem_SelectedItem(object sender, EventArgs e)
    168         {
    169             this.FindForm().ActiveControl = this;
    170             IMenuItem item = sender as IMenuItem;
    171             if (m_lstParentItems.Contains(sender as Control))
    172             {
    173                 if (m_selectParentItem != item)
    174                 {
    175                     if (m_selectParentItem != null)
    176                     {
    177                         m_selectParentItem.SetSelectedStyle(false);
    178                     }
    179                     m_selectParentItem = item;
    180                     m_selectParentItem.SetSelectedStyle(true);
    181                     SetChildrenControl(m_selectParentItem);
    182                 }
    183                 else
    184                 {
    185                     m_selectParentItem.SetSelectedStyle(false);
    186                     m_selectParentItem = null;
    187                     SetChildrenControl(m_selectParentItem, false);
    188                 }
    189             }
    190             else if (m_panChildren.Controls.Contains(sender as Control))
    191             {
    192                 if (m_selectChildrenItem != item)
    193                 {
    194                     if (m_selectChildrenItem != null)
    195                     {
    196                         m_selectChildrenItem.SetSelectedStyle(false);
    197                     }
    198                     m_selectChildrenItem = item;
    199                     m_selectChildrenItem.SetSelectedStyle(true);
    200                 }
    201             }
    202             if (SelectedItem != null)
    203             {
    204                 SelectedItem(sender, e);
    205             }
    206         }
    207 
    208         private void SetChildrenControl(IMenuItem menuitem, bool blnChildren = true)
    209         {
    210             try
    211             {
    212                 ControlHelper.FreezeControl(this, true);
    213                 if (m_menuStyle == HZH_Controls.Controls.MenuStyle.Fill)
    214                 {
    215                     if (blnChildren)
    216                     {
    217                         Control cMenu = menuitem as Control;
    218                         int index = m_lstParentItems.IndexOf(cMenu);
    219                         for (int i = 0; i <= index; i++)
    220                         {
    221                             m_lstParentItems[i].Dock = DockStyle.Top;
    222                             this.Controls.SetChildIndex(m_lstParentItems[i], 1);
    223                         }
    224                         for (int i = index + 1; i < m_lstParentItems.Count; i++)
    225                         {
    226                             m_lstParentItems[i].Dock = DockStyle.Bottom;
    227                             this.Controls.SetChildIndex(m_lstParentItems[i], m_lstParentItems.Count);
    228                         }
    229                         m_panChildren.Controls.Clear();
    230                         int intItemHeigth = 0;
    231                         foreach (var item in menuitem.DataSource.Childrens)
    232                         {
    233                             IMenuItem parentItem = (IMenuItem)Activator.CreateInstance(m_childrenItemType);
    234                             parentItem.DataSource = item;
    235                             if (m_childrenItemStyles != null)
    236                                 parentItem.SetStyle(m_childrenItemStyles);
    237                             parentItem.SelectedItem += parentItem_SelectedItem;
    238                             Control c = parentItem as Control;
    239                             if (intItemHeigth == 0)
    240                                 intItemHeigth = c.Height;
    241                             c.Dock = DockStyle.Top;
    242                             m_panChildren.Controls.Add(c);
    243                             m_panChildren.Controls.SetChildIndex(c, 0);
    244                         }
    245                         //m_panChildren.MinimumSize = new Size(0, menuitem.DataSource.Childrens.Count * intItemHeigth);
    246                     }
    247                     else
    248                     {
    249                         m_panChildren.Controls.Clear();
    250                         foreach (var item in m_lstParentItems)
    251                         {
    252                             item.Dock = DockStyle.Top;
    253                             this.Controls.SetChildIndex(item, 1);
    254                         }
    255                     }
    256                 }
    257                 else
    258                 {
    259                     if (blnChildren)
    260                     {
    261                         Control cMenu = menuitem as Control;
    262                         int index = m_lstParentItems.IndexOf(cMenu);
    263                         this.Controls.SetChildIndex(m_panChildren, m_lstParentItems.Count - index - 1);
    264                         m_panChildren.Controls.Clear();
    265                         int intItemHeigth = 0;
    266                         foreach (var item in menuitem.DataSource.Childrens)
    267                         {
    268                             IMenuItem parentItem = (IMenuItem)Activator.CreateInstance(m_childrenItemType);
    269                             parentItem.DataSource = item;
    270                             if (m_childrenItemStyles != null)
    271                                 parentItem.SetStyle(m_childrenItemStyles);
    272                             parentItem.SelectedItem += parentItem_SelectedItem;
    273                             Control c = parentItem as Control;
    274                             if (intItemHeigth == 0)
    275                                 intItemHeigth = c.Height;
    276                             c.Dock = DockStyle.Top;
    277                             m_panChildren.Controls.Add(c);
    278                             m_panChildren.Controls.SetChildIndex(c, 0);
    279                         }
    280                         m_panChildren.Height = menuitem.DataSource.Childrens.Count * intItemHeigth;
    281                     }
    282                     else
    283                     {
    284                         m_panChildren.Controls.Clear();
    285                         m_panChildren.Height = 0;
    286                     }
    287                 }
    288             }
    289             finally
    290             {
    291                 ControlHelper.FreezeControl(this, false);
    292             }
    293         }
    294 
    295         public UCMenu()
    296         {
    297             InitializeComponent();
    298         }
    299     }
    300 
    301     public enum MenuStyle
    302     {
    303         /// <summary>
    304         /// 平铺
    305         /// </summary>
    306         Fill = 1,
    307         /// <summary>
    308         /// 顶部对齐
    309         /// </summary>
    310         Top = 2,
    311     }
    312 
    313 }
    View Code
     1 namespace HZH_Controls.Controls
     2 {
     3     partial class UCMenu
     4     {
     5         /// <summary> 
     6         /// 必需的设计器变量。
     7         /// </summary>
     8         private System.ComponentModel.IContainer components = null;
     9 
    10         /// <summary> 
    11         /// 清理所有正在使用的资源。
    12         /// </summary>
    13         /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
    14         protected override void Dispose(bool disposing)
    15         {
    16             if (disposing && (components != null))
    17             {
    18                 components.Dispose();
    19             }
    20             base.Dispose(disposing);
    21         }
    22 
    23         #region 组件设计器生成的代码
    24 
    25         /// <summary> 
    26         /// 设计器支持所需的方法 - 不要
    27         /// 使用代码编辑器修改此方法的内容。
    28         /// </summary>
    29         private void InitializeComponent()
    30         {
    31             this.SuspendLayout();
    32             // 
    33             // UCMenu
    34             // 
    35             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
    36             this.AutoScroll = true;
    37             this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(20)))), ((int)(((byte)(30)))), ((int)(((byte)(39)))));
    38             this.Name = "UCMenu";
    39             this.Size = new System.Drawing.Size(204, 468);
    40             this.ResumeLayout(false);
    41 
    42         }
    43 
    44         #endregion
    45 
    46     }
    47 }
    View Code

    用处及效果

    示例代码

    List<MenuItemEntity> lstMenu = new List<MenuItemEntity>();
                for (int i = 0; i < 5; i++)
                {
                    MenuItemEntity item = new MenuItemEntity()
                    {
                        Key = "p" + i.ToString(),
                        Text = "菜单项" + i,
                        DataSource = "这里编写一些自定义的数据源,用于扩展"
                    };
                    item.Childrens = new List<MenuItemEntity>();
                    for (int j = 0; j < 5; j++)
                    {
                        MenuItemEntity item2 = new MenuItemEntity()
                        {
                            Key = "c" + i.ToString(),
                            Text = "菜单子项" + i + "-" + j,
                            DataSource = "这里编写一些自定义的数据源,用于扩展"
                        };
                        item.Childrens.Add(item2);
                    }
                    lstMenu.Add(item);
                }
                this.ucMenu1.MenuStyle = MenuStyle.Top;  
                this.ucMenu1.DataSource = lstMenu;

    最后的话

    如果你喜欢的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 点个星 星吧

  • 相关阅读:
    python主成分分析
    matplotlib绘图pie
    cpu监控:mpstat命令
    cpu监控:dstat
    MongoDB--安装部署
    Linux-网络管理
    Apache 虚拟主机配置
    Apache 访问控制
    Apache 域名跳转配置
    Apache 日志管理
  • 原文地址:https://www.cnblogs.com/bfyx/p/11363432.html
Copyright © 2011-2022 走看看