前提
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control
如果觉得写的还行,请点个 star 支持一下吧
准备工作
该控件是由多个按钮组合形成的,类似多选框和单选框,需要用到前面我们说到的控件UCBtnExt ,如果你对UCBtnExt 还不了解,请移步
我们先理一下思路,我们需要显示多个按钮,支持多选和单选,具有选中效果
开始
我们先看下有哪些属性
1 /// <summary> 2 /// 选中改变事件 3 /// </summary> 4 public event EventHandler SelectedItemChanged; 5 private Dictionary<string, string> m_dataSource = new Dictionary<string, string>(); 6 /// <summary> 7 /// 数据源 8 /// </summary> 9 public Dictionary<string, string> DataSource 10 { 11 get { return m_dataSource; } 12 set 13 { 14 m_dataSource = value; 15 Reload(); 16 } 17 } 18 19 private List<string> m_selectItem = new List<string>(); 20 /// <summary> 21 /// 选中项 22 /// </summary> 23 public List<string> SelectItem 24 { 25 get { return m_selectItem; } 26 set 27 { 28 m_selectItem = value; 29 if (m_selectItem == null) 30 m_selectItem = new List<string>(); 31 SetSelected(); 32 } 33 } 34 35 private bool m_isMultiple = false; 36 /// <summary> 37 /// 是否多选 38 /// </summary> 39 public bool IsMultiple 40 { 41 get { return m_isMultiple; } 42 set { m_isMultiple = value; } 43 }
当数据源改变的时候,需要加载按钮到面板上
1 private void Reload() 2 { 3 try 4 { 5 ControlHelper.FreezeControl(flowLayoutPanel1, true); 6 this.flowLayoutPanel1.Controls.Clear(); 7 if (DataSource != null) 8 { 9 foreach (var item in DataSource) 10 { 11 UCBtnExt btn = new UCBtnExt(); 12 btn.BackColor = System.Drawing.Color.Transparent; 13 btn.BtnBackColor = System.Drawing.Color.White; 14 btn.BtnFont = new System.Drawing.Font("微软雅黑", 10F); 15 btn.BtnForeColor = System.Drawing.Color.Gray; 16 btn.BtnText = item.Value; 17 btn.ConerRadius = 5; 18 btn.Cursor = System.Windows.Forms.Cursors.Hand; 19 btn.FillColor = System.Drawing.Color.White; 20 btn.Font = new System.Drawing.Font("微软雅黑", 15F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel); 21 btn.IsRadius = true; 22 btn.IsShowRect = true; 23 btn.IsShowTips = false; 24 btn.Location = new System.Drawing.Point(5, 5); 25 btn.Margin = new System.Windows.Forms.Padding(5); 26 btn.Name = item.Key; 27 btn.RectColor = System.Drawing.Color.FromArgb(224, 224, 224); 28 btn.RectWidth = 1; 29 btn.Size = new System.Drawing.Size(72, 38); 30 btn.TabStop = false; 31 btn.BtnClick += btn_BtnClick; 32 this.flowLayoutPanel1.Controls.Add(btn); 33 } 34 } 35 } 36 finally 37 { 38 ControlHelper.FreezeControl(flowLayoutPanel1, false); 39 } 40 SetSelected(); 41 } 42 43 void btn_BtnClick(object sender, EventArgs e) 44 { 45 var btn = sender as UCBtnExt; 46 if (m_selectItem.Contains(btn.Name)) 47 { 48 btn.RectColor = System.Drawing.Color.FromArgb(224, 224, 224); 49 m_selectItem.Remove(btn.Name); 50 } 51 else 52 { 53 if (!m_isMultiple) 54 { 55 foreach (var item in m_selectItem) 56 { 57 var lst = this.flowLayoutPanel1.Controls.Find(item, false); 58 if (lst.Length == 1) 59 { 60 var _btn = lst[0] as UCBtnExt; 61 _btn.RectColor = System.Drawing.Color.FromArgb(224, 224, 224); 62 } 63 } 64 m_selectItem.Clear(); 65 } 66 btn.RectColor = System.Drawing.Color.FromArgb(255, 77, 59); 67 m_selectItem.Add(btn.Name); 68 } 69 if (SelectedItemChanged != null) 70 SelectedItemChanged(this, e); 71 }
如果设置了初始选中项,那么还需要在加载后选中
1 private void SetSelected() 2 { 3 if (m_selectItem != null && m_selectItem.Count > 0 && DataSource != null && DataSource.Count > 0) 4 { 5 try 6 { 7 ControlHelper.FreezeControl(flowLayoutPanel1, true); 8 if (m_isMultiple) 9 { 10 foreach (var item in m_selectItem) 11 { 12 var lst = this.flowLayoutPanel1.Controls.Find(item, false); 13 if (lst.Length == 1) 14 { 15 var btn = lst[0] as UCBtnExt; 16 btn.RectColor = System.Drawing.Color.FromArgb(255, 77, 59); 17 } 18 } 19 } 20 else 21 { 22 UCBtnExt btn = null; 23 foreach (var item in m_selectItem) 24 { 25 var lst = this.flowLayoutPanel1.Controls.Find(item, false); 26 if (lst.Length == 1) 27 { 28 btn = lst[0] as UCBtnExt; 29 break; 30 } 31 } 32 if (btn != null) 33 { 34 m_selectItem = new List<string>() { btn.Name }; 35 btn.RectColor = System.Drawing.Color.FromArgb(255, 77, 59); 36 } 37 } 38 } 39 finally 40 { 41 ControlHelper.FreezeControl(flowLayoutPanel1, false); 42 } 43 } 44 }
至此所有的逻辑已经处理完成,下面看下完整的代码吧
1 // 版权所有 黄正辉 交流群:568015492 QQ:623128629 2 // 文件名称:UCBtnsGroup.cs 3 // 创建日期:2019-08-15 15:58:13 4 // 功能描述:按钮组 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 UCBtnsGroup : UserControl 18 { 19 /// <summary> 20 /// 选中改变事件 21 /// </summary> 22 public event EventHandler SelectedItemChanged; 23 private Dictionary<string, string> m_dataSource = new Dictionary<string, string>(); 24 /// <summary> 25 /// 数据源 26 /// </summary> 27 public Dictionary<string, string> DataSource 28 { 29 get { return m_dataSource; } 30 set 31 { 32 m_dataSource = value; 33 Reload(); 34 } 35 } 36 37 private List<string> m_selectItem = new List<string>(); 38 /// <summary> 39 /// 选中项 40 /// </summary> 41 public List<string> SelectItem 42 { 43 get { return m_selectItem; } 44 set 45 { 46 m_selectItem = value; 47 if (m_selectItem == null) 48 m_selectItem = new List<string>(); 49 SetSelected(); 50 } 51 } 52 53 private bool m_isMultiple = false; 54 /// <summary> 55 /// 是否多选 56 /// </summary> 57 public bool IsMultiple 58 { 59 get { return m_isMultiple; } 60 set { m_isMultiple = value; } 61 } 62 public UCBtnsGroup() 63 { 64 InitializeComponent(); 65 } 66 67 private void Reload() 68 { 69 try 70 { 71 ControlHelper.FreezeControl(flowLayoutPanel1, true); 72 this.flowLayoutPanel1.Controls.Clear(); 73 if (DataSource != null) 74 { 75 foreach (var item in DataSource) 76 { 77 UCBtnExt btn = new UCBtnExt(); 78 btn.BackColor = System.Drawing.Color.Transparent; 79 btn.BtnBackColor = System.Drawing.Color.White; 80 btn.BtnFont = new System.Drawing.Font("微软雅黑", 10F); 81 btn.BtnForeColor = System.Drawing.Color.Gray; 82 btn.BtnText = item.Value; 83 btn.ConerRadius = 5; 84 btn.Cursor = System.Windows.Forms.Cursors.Hand; 85 btn.FillColor = System.Drawing.Color.White; 86 btn.Font = new System.Drawing.Font("微软雅黑", 15F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel); 87 btn.IsRadius = true; 88 btn.IsShowRect = true; 89 btn.IsShowTips = false; 90 btn.Location = new System.Drawing.Point(5, 5); 91 btn.Margin = new System.Windows.Forms.Padding(5); 92 btn.Name = item.Key; 93 btn.RectColor = System.Drawing.Color.FromArgb(224, 224, 224); 94 btn.RectWidth = 1; 95 btn.Size = new System.Drawing.Size(72, 38); 96 btn.TabStop = false; 97 btn.BtnClick += btn_BtnClick; 98 this.flowLayoutPanel1.Controls.Add(btn); 99 } 100 } 101 } 102 finally 103 { 104 ControlHelper.FreezeControl(flowLayoutPanel1, false); 105 } 106 SetSelected(); 107 } 108 109 void btn_BtnClick(object sender, EventArgs e) 110 { 111 var btn = sender as UCBtnExt; 112 if (m_selectItem.Contains(btn.Name)) 113 { 114 btn.RectColor = System.Drawing.Color.FromArgb(224, 224, 224); 115 m_selectItem.Remove(btn.Name); 116 } 117 else 118 { 119 if (!m_isMultiple) 120 { 121 foreach (var item in m_selectItem) 122 { 123 var lst = this.flowLayoutPanel1.Controls.Find(item, false); 124 if (lst.Length == 1) 125 { 126 var _btn = lst[0] as UCBtnExt; 127 _btn.RectColor = System.Drawing.Color.FromArgb(224, 224, 224); 128 } 129 } 130 m_selectItem.Clear(); 131 } 132 btn.RectColor = System.Drawing.Color.FromArgb(255, 77, 59); 133 m_selectItem.Add(btn.Name); 134 } 135 if (SelectedItemChanged != null) 136 SelectedItemChanged(this, e); 137 } 138 139 private void SetSelected() 140 { 141 if (m_selectItem != null && m_selectItem.Count > 0 && DataSource != null && DataSource.Count > 0) 142 { 143 try 144 { 145 ControlHelper.FreezeControl(flowLayoutPanel1, true); 146 if (m_isMultiple) 147 { 148 foreach (var item in m_selectItem) 149 { 150 var lst = this.flowLayoutPanel1.Controls.Find(item, false); 151 if (lst.Length == 1) 152 { 153 var btn = lst[0] as UCBtnExt; 154 btn.RectColor = System.Drawing.Color.FromArgb(255, 77, 59); 155 } 156 } 157 } 158 else 159 { 160 UCBtnExt btn = null; 161 foreach (var item in m_selectItem) 162 { 163 var lst = this.flowLayoutPanel1.Controls.Find(item, false); 164 if (lst.Length == 1) 165 { 166 btn = lst[0] as UCBtnExt; 167 break; 168 } 169 } 170 if (btn != null) 171 { 172 m_selectItem = new List<string>() { btn.Name }; 173 btn.RectColor = System.Drawing.Color.FromArgb(255, 77, 59); 174 } 175 } 176 } 177 finally 178 { 179 ControlHelper.FreezeControl(flowLayoutPanel1, false); 180 } 181 } 182 } 183 } 184 }
1 namespace HZH_Controls.Controls 2 { 3 partial class UCBtnsGroup 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.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); 32 this.SuspendLayout(); 33 // 34 // flowLayoutPanel1 35 // 36 this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; 37 this.flowLayoutPanel1.Location = new System.Drawing.Point(0, 0); 38 this.flowLayoutPanel1.Name = "flowLayoutPanel1"; 39 this.flowLayoutPanel1.Size = new System.Drawing.Size(420, 50); 40 this.flowLayoutPanel1.TabIndex = 0; 41 // 42 // UCBtnsGroup 43 // 44 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; 45 this.BackColor = System.Drawing.Color.White; 46 this.Controls.Add(this.flowLayoutPanel1); 47 this.MinimumSize = new System.Drawing.Size(0, 50); 48 this.Name = "UCBtnsGroup"; 49 this.Size = new System.Drawing.Size(420, 50); 50 this.ResumeLayout(false); 51 52 } 53 54 #endregion 55 56 private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; 57 } 58 }
用处及效果
用处:可以用选择按钮组来替换单选框和复选框,具有更和谐的界面效果
效果:
最后的话
如果你喜欢的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 点个星星吧