前提 入行已經7,8年了,一直想做一套漂亮點的自定義控制項,於是就有了本系列文章。 GitHub:https://github.com/kwwwvagaa/NetWinformControl 碼雲:https://gitee.com/kwwwvagaa/net_winform_custom_contr ...
前提
入行已經7,8年了,一直想做一套漂亮點的自定義控制項,於是就有了本系列文章。
GitHub:https://github.com/kwwwvagaa/NetWinformControl
碼雲:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
如果覺得寫的還行,請點個 star 支持一下吧
麻煩博客下方點個【推薦】,謝謝
NuGet
Install-Package HZH_Controls
目錄
https://www.cnblogs.com/bfyx/p/11364884.html
用處及效果
準備工作
這個是在前面表格的基礎上,擴展了自定義行實現的,當然也修改了一些列表控制項以相容
如果對前面的表格控制項不瞭解,請移步查看
開始
實現樹表格的思路就是,在行控制項中再添加一個無標題的表格控制項,當需要顯示子節點的時候,將子節點數據載入到行里的表格控制項中,然後處理一下事件,讓事件可以穿透到最頂層就行了。
另外我們前面表格中的行個數是根據高度大小自動計算的,這裡就會出現問題,當出現子節點表格的時候,就會導致重算個數和高度,所有我們在表格列表控制項增加一個屬性來禁用這個自動計算。
添加一個用戶控制項,命名UCDataGridViewTreeRow,實現介面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 int m_rowHeight = 40; 44 public int RowHeight 45 { 46 get 47 { 48 return m_rowHeight; 49 } 50 set 51 { 52 m_rowHeight = value; 53 this.Height = value; 54 } 55 } 56 #endregion
構造函數處理一寫東西,註意 this.ucDGVChild.ItemClick ,這個是將子節點表格的點擊事件向上傳遞
1 public UCDataGridViewTreeRow() 2 { 3 InitializeComponent(); 4 this.ucDGVChild.RowType = this.GetType(); 5 this.ucDGVChild.IsAutoHeight = true; 6 this.SizeChanged += UCDataGridViewTreeRow_SizeChanged; 7 this.ucDGVChild.ItemClick += (a, b) => 8 { 9 if (CellClick != null) 10 { 11 CellClick(a, new DataGridViewEventArgs() 12 { 13 CellControl = (a as Control), 14 CellIndex = (a as Control).Tag.ToInt() 15 }); 16 } 17 }; 18 19 }
實現介面函數BindingCellData,主要處理一下數據綁定後將子節點數據向下傳遞
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 panLeft.Tag = 0; 25 var proChildrens = DataSource.GetType().GetProperty("Childrens"); 26 if (proChildrens != null) 27 { 28 var value = proChildrens.GetValue(DataSource, null); 29 if (value != null) 30 { 31 int intSourceCount = 0; 32 if (value is DataTable) 33 { 34 intSourceCount = (value as DataTable).Rows.Count; 35 } 36 else if (typeof(IList).IsAssignableFrom(value.GetType())) 37 { 38 intSourceCount = (value as IList).Count; 39 } 40 if (intSourceCount > 0) 41 { 42 panLeft.BackgroundImage = Properties.Resources.caret_right; 43 panLeft.Enabled = true; 44 panChildGrid.Tag = value; 45 } 46 else 47 { 48 panLeft.BackgroundImage = null; 49 panLeft.Enabled = false; 50 panChildGrid.Tag = null; 51 } 52 } 53 else 54 { 55 panLeft.BackgroundImage = null; 56 panLeft.Enabled = false; 57 panChildGrid.Tag = null; 58 } 59 } 60 else 61 { 62 panLeft.BackgroundImage = null; 63 panLeft.Enabled = false; 64 panChildGrid.Tag = null; 65 } 66 }
實現函數綁定列
1 public void ReloadCells() 2 { 3 try 4 { 5 ControlHelper.FreezeControl(this, true); 6 this.panCells.Controls.Clear(); 7 this.panCells.ColumnStyles.Clear(); 8 9 int intColumnsCount = Columns.Count(); 10 if (Columns != null && intColumnsCount > 0) 11 { 12 if (IsShowCheckBox) 13 { 14 intColumnsCount++; 15 } 16 this.panCells.ColumnCount = intColumnsCount; 17 for (int i = 0; i < intColumnsCount; i++) 18 { 19 Control c = null; 20 if (i == 0 && IsShowCheckBox) 21 { 22 this.panCells.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(SizeType.Absolute, 30F)); 23 24 UCCheckBox box = new UCCheckBox(); 25 box.Name = "check"; 26 box.TextValue = ""; 27 box.Size = new Size(30, 30); 28 box.Dock = DockStyle.Fill; 29 box.CheckedChangeEvent += (a, b) => 30 { 31 IsChecked = box.Checked; 32 this.ucDGVChild.Rows.ForEach(p => p.IsChecked = box.Checked); 33 if (CheckBoxChangeEvent != null) 34 { 35 CheckBoxChangeEvent(a, new DataGridViewEventArgs() 36 { 37 CellControl = box, 38 CellIndex = 0 39 }); 40 } 41 }; 42 c = box; 43 } 44 else 45 { 46 var item = Columns[i - (IsShowCheckBox ? 1 : 0)]; 47 this.panCells.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(item.WidthType, item.Width)); 48 49 Label lbl = new Label(); 50 lbl.Tag = i - (IsShowCheckBox ? 1 : 0); 51 lbl.Name = "lbl_" + item.DataField; 52 lbl.Font = new Font("微軟雅黑", 12); 53 lbl.ForeColor = Color.Black; 54 lbl.AutoSize = false; 55 lbl.Dock = DockStyle.Fill; 56 lbl.TextAlign = ContentAlignment.MiddleCenter; 57 lbl.MouseDown += (a, b) => 58 { 59 Item_MouseDown(a, b); 60 }; 61 c = lbl; 62 } 63 this.panCells.Controls.Add(c, i, 0); 64 } 65 66 } 67 } 68 finally 69 { 70 ControlHelper.FreezeControl(this, false); 71 } 72 }
當點擊展開圖標的時候處理子節點的數據綁定以及高度計算
1 private void panLeft_MouseDown(object sender, MouseEventArgs e) 2 { 3 try 4 { 5 ControlHelper.FreezeControl(this.FindForm(), true); 6 if (panLeft.Tag.ToInt() == 0) 7 { 8 var value = panChildGrid.Tag; 9 if (value != null) 10 { 11 panLeft.BackgroundImage = Properties.Resources.caret_down; 12 panLeft.Tag = 1; 13 int intSourceCount = 0; 14 if (value is DataTable) 15 { 16 intSourceCount = (value as DataTable).Rows.Count; 17 } 18 else if (typeof(IList).IsAssignableFrom(value.GetType())) 19 { 20 intSourceCount = (value as IList).Count; 21 } 22 this.panChildGrid.Height = RowHeight * intSourceCount; 23 if (panChildGrid.Height > 0) 24 { 25 if (value != this.ucDGVChild.DataSource) 26 { 27 this.ucDGVChild.Columns = Columns; 28 this.ucDGVChild.RowHeight = RowHeight; 29 this.ucDGVChild.HeadPadingLeft = this.panLeft.Width; 30 this.ucDGVChild.IsShowCheckBox = IsShowCheckBox; 31 this.ucDGVChild.DataSource = value; 32 this.ucDGVChild.Rows.ForEach(p => p.IsChecked =this.IsChecked); 33 } 34 } 35 } 36 37 } 38 else 39 { 40 panLeft.Tag = 0; 41 panChildGrid.Height = 0; 42 panLeft.BackgroundImage = Properties.Resources.caret_right; 43 } 44 } 45 finally 46 { 47 ControlHelper.FreezeControl(this.FindForm(), false); 48 } 49 }
承載子節點表格的panel 在大小改變的時候,處理父級表格的大小。來防止出現多個滾動條
1 void UCDataGridViewTreeRow_SizeChanged(object sender, EventArgs e) 2 { 3 if (this.Parent.Parent.Parent != null && this.Parent.Parent.Parent.Name == "panChildGrid" && this.panLeft.Tag.ToInt() == 1) 4 { 5 int intHeight = this.Parent.Parent.Controls[0].Controls.ToArray().Sum(p => p.Height); 6 if (this.Parent.Parent.Parent.Height != intHeight) 7 this.Parent.Parent.Parent.Height = intHeight; 8 } 9 }
完整代碼
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Drawing; 5 using System.Data; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.Collections; 10 11 namespace HZH_Controls.Controls 12 { 13 [ToolboxItem(false)] 14 public partial class UCDataGridViewTreeRow : UserControl, IDataGridViewRow 15 { 16 #region 屬性 17 public event DataGridViewEventHandler CheckBoxChangeEvent; 18 19 public event DataGridViewEventHandler CellClick; 20 21 public event DataGridViewEventHandler SourceChanged; 22 23 public List<DataGridViewColumnEntity> Columns 24 { 25 get; 26 set; 27 } 28 29 public object DataSource 30 { 31 get; 32 set; 33 } 34 35 public bool IsShowCheckBox 36 { 37 get; 38 set; 39 } 40 private bool m_isChecked; 41 public bool IsChecked 42 { 43 get 44 { 45 return m_isChecked; 46 } 47 48 set 49 { 50 if (m_isChecked != value) 51 { 52 m_isChecked = value; 53 (this.panCells.Controls.Find("check", false)[0] as UCCheckBox).Checked = value; 54 } 55 } 56 } 57 58 int m_rowHeight = 40; 59 public int RowHeight 60 { 61 get 62 { 63 return m_rowHeight; 64 } 65 set 66 { 67 m_rowHeight = value; 68 this.Height = value; 69 } 70 } 71 #endregion 72 73 public UCDataGridViewTreeRow() 74 { 75 InitializeComponent(); 76 this.ucDGVChild.RowType = this.GetType(); 77 this.ucDGVChild.IsAutoHeight = true; 78 this.SizeChanged += UCDataGridViewTreeRow_SizeChanged; 79 this.ucDGVChild.ItemClick += (a, b) => 80 { 81 if (CellClick != null) 82 { 83 CellClick(a, new DataGridViewEventArgs() 84 { 85 CellControl = (a as Control), 86 CellIndex = (a as Control).Tag.ToInt() 87 }); 88 } 89 }; 90 91 } 92 93 void UCDataGridViewTreeRow_SizeChanged(object sender, EventArgs e) 94 { 95 if (this.Parent.Parent.Parent != null && this.Parent.Parent.Parent.Name == "panChildGrid" && this.panLeft.Tag.ToInt() == 1) 96 { 97 int intHeight = this.Parent.Parent.Controls[0].Controls.ToArray().Sum(p => p.Height); 98 if (this.Parent.Parent.Parent.Height != intHeight) 99 this.Parent.Parent.Parent.Height = intHeight; 100 } 101 } 102 103 104 public void BindingCellData() 105 { 106 for (int i = 0; i < Columns.Count; i++) 107 { 108 DataGridViewColumnEntity com = Columns[i]; 109 var cs = this.panCells.Controls.Find("lbl_" + com.DataField, false); 110 if (cs != null && cs.Length > 0) 111 { 112 var pro = DataSource.GetType().GetProperty(com.DataField); 113 if (pro != null) 114 { 115 var value = pro.GetValue(DataSource, null); 116 if (com.Format != null) 117 { 118 cs[0].Text = com.Format(value); 119 } 120 else 121 { 122 cs[0].Text = value.ToStringExt(); 123 } 124 } 125 } 126 } 127 panLeft.Tag = 0; 128 var proChildrens = DataSource.GetType().GetProperty("Childrens"); 129 if (proChildrens != null) 130 { 131 var value = proChildrens.GetValue(DataSource, null); 132 if (value != null) 133 { 134 int intSourceCount = 0; 135 if (value is DataTable) 136 { 137 intSourceCount = (value as DataTable).Rows.Count; 138 } 139 else if (typeof(IList).IsAssignableFrom(value.GetType())) 140 { 141 intSourceCount = (value as IList).Count; 142 } 143 if (intSourceCount > 0) 144 { 145 panLeft.BackgroundImage = Properties.Resources.caret_right; 146 panLeft.Enabled = true; 147 panChildGrid.Tag = value; 148 } 149 else 150 { 151 panLeft.BackgroundImage = null; 152 panLeft.Enabled = false; 153 panChildGrid.Tag = null; 154 } 155 } 156 else 157 { 158 panLeft.BackgroundImage = null; 159 panLeft.Enabled = false; 160 panChildGrid.Tag = null; 161 } 162 } 163 else 164 { 165 panLeft.BackgroundImage = null; 166 panLeft.Enabled = false; 167 panChildGrid.Tag = null; 168 } 169 } 170 171 void Item_MouseDown(object sender, MouseEventArgs e) 172 { 173 if (CellClick != null) 174