(四十七)c#Winform自定義控制項-樹表格(treeGrid)

来源:https://www.cnblogs.com/bfyx/archive/2019/08/26/11412899.html
-Advertisement-
Play Games

前提 入行已經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 支持一下吧

歡迎前來交流探討: 企鵝群568015492 企鵝群568015492

麻煩博客下方點個【推薦】,謝謝

NuGet

Install-Package HZH_Controls

目錄

https://www.cnblogs.com/bfyx/p/11364884.html

用處及效果

準備工作

這個是在前面表格的基礎上,擴展了自定義行實現的,當然也修改了一些列表控制項以相容

如果對前面的表格控制項不瞭解,請移步查看

(三十二)c#Winform自定義控制項-表格

開始

實現樹表格的思路就是,在行控制項中再添加一個無標題的表格控制項,當需要顯示子節點的時候,將子節點數據載入到行里的表格控制項中,然後處理一下事件,讓事件可以穿透到最頂層就行了。

另外我們前面表格中的行個數是根據高度大小自動計算的,這裡就會出現問題,當出現子節點表格的時候,就會導致重算個數和高度,所有我們在表格列表控制項增加一個屬性來禁用這個自動計算。

 

添加一個用戶控制項,命名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       

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • .NETCoreCSharp 中級篇2 6 本節內容為Json和XML操作 簡介 Json和XML文本是電腦網路通信中常見的文本格式,其中Json其實就是JavaScript中的數組與對象,體現了一種面向對象的方式,而XML則是一種可標記語言,類似於我們的html標簽,他更多的是體現一種層級關係。 ...
  • CLR自動維護一個稱為”內置池“(暫存池)(intern pool)的表,在編譯時此表包含程式中聲明的每個唯一的字元串常量的單個實例,以及以編程方式創建的String類的任何唯一實例。 內置池被實現為散列表。使用散列表即表示,一個字元串可以通過一個數字或”散列碼“來表示。這樣比較和搜索字元串就非常有 ...
  • 最近受人之托研究了下b站的數據爬取做個小工具,最後朋友說不需要了,本著開源共用的原則,將研究成果與大家分享一波,話不多說直接上乾貨 需求分析 給定up主uid和用戶uid,爬取用戶在該up主所有視頻中發的所有彈幕 需求拆解 獲取up主所有視頻 打開b站,隨便搜索一個up主,打開所有視頻頁面,f12看 ...
  • 之前查找靜態構造函數相關的問題無意間碰到的一個問題。改變控制台的背景顏色。 這段代碼運行以後是這個樣子的。和想要的結果不符合。 所以正確的代碼其實是 只多了一行 Console.Clear(); 結束 ...
  • 上接(abp(net core)+easyui+efcore實現倉儲管理系統——使用 WEBAPI實現CURD (十四)),在這一篇文章中我們實現更新與刪除供應商的相關功能。 至此,完成了供應商信息的增刪改查,但是我們沒有寫一行與增刪改查有關的c#代碼,都是由ABP提供了AsyncCrudA... ...
  • 最近研究了PIE SDK文本元素的繪製相關內容,因為在我們的開發中,希望可以做到在打開一個Shp文件後,讀取到屬性表的所有欄位,然後可以選擇一些需要的欄位,將這些欄位的所有要素值的文本,繪製到shp圖中相應的要素位置上。 我主要是通過PIE的官方博文(https://www.cnblogs.com/ ...
  • 場景 Winform中DevExpress的TreeList的入門使用教程(附源碼下載): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/100075677 https://www.cnblogs.com/badaoliumang ...
  • 客服消息簡介 當用戶和公眾號產生特定動作的交互時(具體動作列表請見下方說明),微信將會把消息數據推送給開發者,開發者可以在一段時間內(目前修改為48小時)調用客服介面,通過POST一個JSON數據包來發送消息給普通用戶。此介面主要用於客服等有人工消息處理環節的功能,方便開發者為用戶提供更加優質的服務 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...