前提
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
GitHub:https://github.com/kwwwvagaa/NetWinformControl
码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
如果觉得写的还行,请点个 star 支持一下吧
目录
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 }