前提 入行已經7,8年了,一直想做一套漂亮點的自定義控制項,於是就有了本系列文章。 開源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control 如果覺得寫的還行,請點個 star 支持一下吧 歡迎前來交流探討: 企鵝群568015492 目錄 ...
前提
入行已經7,8年了,一直想做一套漂亮點的自定義控制項,於是就有了本系列文章。
開源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control
如果覺得寫的還行,請點個 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.TextValue = ""; 146 box.Size = new Size(30, 30); 147 box.Dock = DockStyle.Fill; 148 box.CheckedChangeEvent += (a, b) => 149 { 150 IsChecked = box.Checked; 151 if (CheckBoxChangeEvent != null) 152 { 153 CheckBoxChangeEvent(a, new DataGridViewEventArgs() 154 { 155 CellControl = box, 156 CellIndex = 0 157 }); 158 } 159 }; 160 c = box; 161 } 162 else 163 { 164 var item = Columns[i - (IsShowCheckBox ? 1 : 0)]; 165 this.panCells.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(item.WidthType, item.Width)); 166 167 Label lbl = new Label(); 168 lbl.Tag = i - (IsShowCheckBox ? 1 : 0); 169 lbl.Name = "lbl_" + item.DataField; 170 lbl.Font = new Font("微軟雅黑", 12); 171 lbl.ForeColor = Color.Black; 172 lbl.AutoSize = false; 173 lbl.Dock = DockStyle.Fill; 174 lbl.TextAlign = ContentAlignment.MiddleCenter; 175 lbl.MouseDown += (a, b) => 176 { 177 Item_MouseDown(a, b); 178 }; 179 c = lbl; 180 } 181 this.panCells.Controls.Add(c, i, 0); 182 } 183 184 } 185 } 186 finally 187 { 188 ControlHelper.FreezeControl(this, false); 189 } 190 } 191 192 193 } 194 }View Code
1 namespace HZH_Controls.Controls 2 { 3 partial class UCDataGridViewRow 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 {