前提
入行已经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部分,1:行元素控件,2:列表控件
为了具有更好的扩展性,更加的open,使用接口对行元素进行约束,当行样式或功能不满足你的需求的时候,可以自定义一个行元素,实现接口控件,然后将类型指定给列表控件即可
表格控件用到了分页控件,如果你还没有对分页控件进行了解,请移步查看
开始
定义一些辅助东西
1 public class DataGridViewCellEntity 2 { 3 public string Title { get; set; } 4 public int Width { get; set; } 5 public System.Windows.Forms.SizeType WidthType { get; set; } 6 7 }
1 public class DataGridViewEventArgs : EventArgs 2 { 3 public Control CellControl { get; set; } 4 public int CellIndex { get; set; } 5 public int RowIndex { get; set; } 6 7 8 }
1 [Serializable] 2 [ComVisible(true)] 3 public delegate void DataGridViewEventHandler(object sender, DataGridViewEventArgs e);
1 public class DataGridViewColumnEntity 2 { 3 public string HeadText { get; set; } 4 public int Width { get; set; } 5 public System.Windows.Forms.SizeType WidthType { get; set; } 6 public string DataField { get; set; } 7 public Func<object, string> Format { get; set; } 8 }
定义行接口
1 public interface IDataGridViewRow 2 { 3 /// <summary> 4 /// CheckBox选中事件 5 /// </summary> 6 event DataGridViewEventHandler CheckBoxChangeEvent; 7 /// <summary> 8 /// 点击单元格事件 9 /// </summary> 10 event DataGridViewEventHandler CellClick; 11 /// <summary> 12 /// 数据源改变事件 13 /// </summary> 14 event DataGridViewEventHandler SourceChanged; 15 /// <summary> 16 /// 列参数,用于创建列数和宽度 17 /// </summary> 18 List<DataGridViewColumnEntity> Columns { get; set; } 19 bool IsShowCheckBox { get; set; } 20 /// <summary> 21 /// 是否选中 22 /// </summary> 23 bool IsChecked { get; set; } 24 25 /// <summary> 26 /// 数据源 27 /// </summary> 28 object DataSource { get; set; } 29 /// <summary> 30 /// 添加单元格元素,仅做添加控件操作,不做数据绑定,数据绑定使用BindingCells 31 /// </summary> 32 void ReloadCells(); 33 /// <summary> 34 /// 绑定数据到Cell 35 /// </summary> 36 /// <param name="intIndex">cell下标</param> 37 /// <returns>返回true则表示已处理过,否则将进行默认绑定(通常只针对有Text值的控件)</returns> 38 void BindingCellData(); 39 /// <summary> 40 /// 设置选中状态,通常为设置颜色即可 41 /// </summary> 42 /// <param name="blnSelected">是否选中</param> 43 void SetSelect(bool blnSelected); 44 }
创建行控件
添加一个用户控件,命名UCDataGridViewRow,实现接口IDataGridViewRow
属性
1 #region 属性 2 public event DataGridViewEventHandler CheckBoxChangeEvent; 3 4 public event DataGridViewEventHandler CellClick; 5 6 public event DataGridViewEventHandler SourceChanged; 7 8 public List<DataGridViewColumnEntity> Columns 9 { 10 get; 11 set; 12 } 13 14 public object DataSource 15 { 16 get; 17 set; 18 } 19 20 public bool IsShowCheckBox 21 { 22 get; 23 set; 24 } 25 private bool m_isChecked; 26 public bool IsChecked 27 { 28 get 29 { 30 return m_isChecked; 31 } 32 33 set 34 { 35 if (m_isChecked != value) 36 { 37 m_isChecked = value; 38 (this.panCells.Controls.Find("check", false)[0] as UCCheckBox).Checked = value; 39 } 40 } 41 } 42 43 44 #endregion
实现接口
1 public void BindingCellData() 2 { 3 for (int i = 0; i < Columns.Count; i++) 4 { 5 DataGridViewColumnEntity com = Columns[i]; 6 var cs = this.panCells.Controls.Find("lbl_" + com.DataField, false); 7 if (cs != null && cs.Length > 0) 8 { 9 var pro = DataSource.GetType().GetProperty(com.DataField); 10 if (pro != null) 11 { 12 var value = pro.GetValue(DataSource, null); 13 if (com.Format != null) 14 { 15 cs[0].Text = com.Format(value); 16 } 17 else 18 { 19 cs[0].Text = value.ToStringExt(); 20 } 21 } 22 } 23 } 24 } 25 26 public void SetSelect(bool blnSelected) 27 { 28 if (blnSelected) 29 { 30 this.BackColor = Color.FromArgb(255, 247, 245); 31 } 32 else 33 { 34 this.BackColor = Color.Transparent; 35 } 36 } 37 38 public void ReloadCells() 39 { 40 try 41 { 42 ControlHelper.FreezeControl(this, true); 43 this.panCells.Controls.Clear(); 44 this.panCells.ColumnStyles.Clear(); 45 46 int intColumnsCount = Columns.Count(); 47 if (Columns != null && intColumnsCount > 0) 48 { 49 if (IsShowCheckBox) 50 { 51 intColumnsCount++; 52 } 53 this.panCells.ColumnCount = intColumnsCount; 54 for (int i = 0; i < intColumnsCount; i++) 55 { 56 Control c = null; 57 if (i == 0 && IsShowCheckBox) 58 { 59 this.panCells.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(SizeType.Absolute, 30F)); 60 61 UCCheckBox box = new UCCheckBox(); 62 box.Name = "check"; 63 box.TextValue = ""; 64 box.Size = new Size(30, 30); 65 box.Dock = DockStyle.Fill; 66 box.CheckedChangeEvent += (a, b) => 67 { 68 IsChecked = box.Checked; 69 if (CheckBoxChangeEvent != null) 70 { 71 CheckBoxChangeEvent(a, new DataGridViewEventArgs() 72 { 73 CellControl = box, 74 CellIndex = 0 75 }); 76 } 77 }; 78 c = box; 79 } 80 else 81 { 82 var item = Columns[i - (IsShowCheckBox ? 1 : 0)]; 83 this.panCells.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(item.WidthType, item.Width)); 84 85 Label lbl = new Label(); 86 lbl.Tag = i - (IsShowCheckBox ? 1 : 0); 87 lbl.Name = "lbl_" + item.DataField; 88 lbl.Font = new Font("微软雅黑", 12); 89 lbl.ForeColor = Color.Black; 90 lbl.AutoSize = false; 91 lbl.Dock = DockStyle.Fill; 92 lbl.TextAlign = ContentAlignment.MiddleCenter; 93 lbl.MouseDown += (a, b) => 94 { 95 Item_MouseDown(a, b); 96 }; 97 c = lbl; 98 } 99 this.panCells.Controls.Add(c, i, 0); 100 } 101 102 } 103 } 104 finally 105 { 106 ControlHelper.FreezeControl(this, false); 107 } 108 }
节点选中事件
1 void Item_MouseDown(object sender, MouseEventArgs e) 2 { 3 if (CellClick != null) 4 { 5 CellClick(sender, new DataGridViewEventArgs() 6 { 7 CellControl = this, 8 CellIndex = (sender as Control).Tag.ToInt() 9 }); 10 } 11 }
完整的代码
1 // 版权所有 黄正辉 交流群:568015492 QQ:623128629 2 // 文件名称:UCDataGridViewRow.cs 3 // 创建日期:2019-08-15 15:59:31 4 // 功能描述:DataGridView 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 [ToolboxItem(false)] 18 public partial class UCDataGridViewRow : UserControl, IDataGridViewRow 19 { 20 21 #region 属性 22 public event DataGridViewEventHandler CheckBoxChangeEvent; 23 24 public event DataGridViewEventHandler CellClick; 25 26 public event DataGridViewEventHandler SourceChanged; 27 28 public List<DataGridViewColumnEntity> Columns 29 { 30 get; 31 set; 32 } 33 34 public object DataSource 35 { 36 get; 37 set; 38 } 39 40 public bool IsShowCheckBox 41 { 42 get; 43 set; 44 } 45 private bool m_isChecked; 46 public bool IsChecked 47 { 48 get 49 { 50 return m_isChecked; 51 } 52 53 set 54 { 55 if (m_isChecked != value) 56 { 57 m_isChecked = value; 58 (this.panCells.Controls.Find("check", false)[0] as UCCheckBox).Checked = value; 59 } 60 } 61 } 62 63 64 #endregion 65 66 public UCDataGridViewRow() 67 { 68 InitializeComponent(); 69 } 70 71 public void BindingCellData() 72 { 73 for (int i = 0; i < Columns.Count; i++) 74 { 75 DataGridViewColumnEntity com = Columns[i]; 76 var cs = this.panCells.Controls.Find("lbl_" + com.DataField, false); 77 if (cs != null && cs.Length > 0) 78 { 79 var pro = DataSource.GetType().GetProperty(com.DataField); 80 if (pro != null) 81 { 82 var value = pro.GetValue(DataSource, null); 83 if (com.Format != null) 84 { 85 cs[0].Text = com.Format(value); 86 } 87 else 88 { 89 cs[0].Text = value.ToStringExt(); 90 } 91 } 92 } 93 } 94 } 95 96 void Item_MouseDown(object sender, MouseEventArgs e) 97 { 98 if (CellClick != null) 99 { 100 CellClick(sender, new DataGridViewEventArgs() 101 { 102 CellControl = this, 103 CellIndex = (sender as Control).Tag.ToInt() 104 }); 105 } 106 } 107 108 public void SetSelect(bool blnSelected) 109 { 110 if (blnSelected) 111 { 112 this.BackColor = Color.FromArgb(255, 247, 245); 113 } 114 else 115 { 116 this.BackColor = Color.Transparent; 117 } 118 } 119 120 public void ReloadCells() 121 { 122 try 123 { 124 ControlHelper.FreezeControl(this, true); 125 this.panCells.Controls.Clear(); 126 this.panCells.ColumnStyles.Clear(); 127 128 int intColumnsCount = Columns.Count(); 129 if (Columns != null && intColumnsCount > 0) 130 { 131 if (IsShowCheckBox) 132 { 133 intColumnsCount++; 134 } 135 this.panCells.ColumnCount = intColumnsCount; 136 for (int i = 0; i < intColumnsCount; i++) 137 { 138 Control c = null; 139 if (i == 0 && IsShowCheckBox) 140 { 141 this.panCells.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(SizeType.Absolute, 30F)); 142 143 UCCheckBox box = new UCCheckBox(); 144 box.Name = "check"; 145 box