主頁 > .NET開發 > Winform組合ComboBox和TreeView實作ComboTreeView

Winform組合ComboBox和TreeView實作ComboTreeView

2020-09-25 07:21:15 .NET開發

最近做Winform專案需要用到類似ComboBox的TreeView控制元件,

雖然各種第三方控制元件很多,但是存在各種版本不兼容問題,所以自己寫了個簡單的ComboTreeView控制元件,

下圖是實作效果:

目前實作的比較簡單,能滿足我專案中的需求,

此處是專案中的代碼簡化后的版本,供大家參考,

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Windows.Forms;
  4 
  5 namespace CustomControl.Tree
  6 {
  7     public abstract class ComboTreeView<T> : ComboBox where T : class
  8     {
  9         protected const int WM_LBUTTONDOWN = 0x0201, WM_LBUTTONDBLCLK = 0x0203;
 10 
 11         protected TreeView treeView;
 12         protected ToolStripControlHost treeViewHost;
 13         protected ToolStripDropDown dropDown;
 14         protected bool dropDownOpen = false;
 15         protected TreeNode selectedNode;
 16         protected T toBeSelected;
 17 
 18         public ComboTreeView(TreeView internalTreeView)
 19         {
 20             if (null == internalTreeView)
 21             {
 22                 throw new ArgumentNullException("internalTreeView");
 23             }
 24             this.InitializeControls(internalTreeView);
 25         }
 26 
 27         public event TreeNodeChangedEventHandler TreeNodeChanged;
 28 
 29         protected virtual void InitializeControls(TreeView internalTreeView)
 30         {
 31             this.treeView = internalTreeView;
 32             this.treeView.BorderStyle = BorderStyle.FixedSingle;
 33             this.treeView.Margin = new Padding(0);
 34             this.treeView.Padding = new Padding(0);
 35             this.treeView.AfterExpand += new TreeViewEventHandler(this.WhenAfterExpand);
 36 
 37             this.treeViewHost = new ToolStripControlHost(this.treeView);
 38             this.treeViewHost.Margin = new Padding(0);
 39             this.treeViewHost.Padding = new Padding(0);
 40             this.treeViewHost.AutoSize = false;
 41 
 42             this.dropDown = new ToolStripDropDown();
 43             this.dropDown.Margin = new Padding(0);
 44             this.dropDown.Padding = new Padding(0);
 45             this.dropDown.AutoSize = false;
 46             this.dropDown.DropShadowEnabled = true;
 47             this.dropDown.Items.Add(this.treeViewHost);
 48             this.dropDown.Closed += new ToolStripDropDownClosedEventHandler(this.OnDropDownClosed);
 49 
 50             this.DropDownWidth = this.Width;
 51             base.DropDownStyle = ComboBoxStyle.DropDownList;
 52             base.SizeChanged += new EventHandler(this.WhenComboboxSizeChanged);
 53         }
 54 
 55         public new ComboBoxStyle DropDownStyle
 56         {
 57             get { return base.DropDownStyle; }
 58             set { base.DropDownStyle = ComboBoxStyle.DropDownList; }
 59         }
 60 
 61         public virtual TreeNode SelectedNode
 62         {
 63             get { return this.selectedNode; }
 64             private set { this.treeView.SelectedNode = value; }
 65         }
 66 
 67         public virtual T SelectedNodeData
 68         {
 69             get { return (T)base.SelectedItem; }
 70             set
 71             {
 72                 this.toBeSelected = value;
 73                 this.UpdateComboBox(value);
 74             }
 75         }
 76 
 77         protected new int SelectedIndex
 78         {
 79             get { return base.SelectedIndex; }
 80             set { base.SelectedIndex = value; }
 81         }
 82 
 83         protected new object SelectedItem
 84         {
 85             get { return base.SelectedItem; }
 86             set { base.SelectedItem = value; }
 87         }
 88 
 89         public virtual string DisplayMember { get; set; } = "Name";
 90 
 91         /// <summary>Gets the internal TreeView control.</summary>
 92         public virtual TreeView TreeView => this.treeView;
 93 
 94         /// <summary>Gets the collection of tree nodes that are assigned to the tree view control.</summary>
 95         /// <returns>A <see cref="T:System.Windows.Forms.TreeNodeCollection" /> that represents the tree nodes assigned to the tree view control.</returns>
 96         public virtual TreeNodeCollection Nodes => this.treeView.Nodes;
 97 
 98         public new int DropDownHeight { get; set; } = 100;
 99 
100         public new int DropDownWidth { get; set; } = 100;
101 
102         protected virtual void ShowDropDown()
103         {
104             this.dropDown.Width = this.Width;
105             this.dropDown.Height = this.DropDownHeight;
106             this.treeViewHost.Width = this.Width;
107             this.treeViewHost.Height = this.DropDownHeight;
108             this.treeView.Font = this.Font;
109             this.dropDown.Focus();
110             this.dropDownOpen = true;
111             this.dropDown.Show(this, 0, base.Height);
112         }
113 
114         protected virtual void HideDropDown()
115         {
116             this.dropDown.Hide();
117             this.dropDownOpen = false;
118         }
119 
120         protected virtual void ToggleDropDown()
121         {
122             if (!this.dropDownOpen)
123             {
124                 this.ShowDropDown();
125             }
126             else
127             {
128                 this.HideDropDown();
129             }
130         }
131 
132         protected override void WndProc(ref Message m)
133         {
134             if ((WM_LBUTTONDOWN == m.Msg) || (WM_LBUTTONDBLCLK == m.Msg))
135             {
136                 if (!this.Focused)
137                 {
138                     this.Focus();
139                 }
140                 this.ToggleDropDown();
141             }
142             else
143             {
144                 base.WndProc(ref m);
145             }
146         }
147 
148         protected override void Dispose(bool disposing)
149         {
150             if (disposing)
151             {
152                 if (this.dropDown != null)
153                 {
154                     this.dropDown.Dispose();
155                     this.dropDown = null;
156                 }
157             }
158             base.Dispose(disposing);
159         }
160 
161         protected virtual void WhenTreeNodeChanged(TreeNode newValue)
162         {
163             if ((null != this.selectedNode) || (null != newValue))
164             {
165                 bool changed;
166                 if ((null != this.selectedNode) && (null != newValue))
167                 {
168                     changed = (this.selectedNode.GetHashCode() != newValue.GetHashCode());
169                 }
170                 else
171                 {
172                     changed = true;
173                 }
174 
175                 if (changed)
176                 {
177                     if (null != this.TreeNodeChanged)
178                     {
179                         try
180                         {
181                             this.TreeNodeChanged.Invoke(this, new TreeNodeChangedEventArgs(this.selectedNode, newValue));
182                         }
183                         catch (Exception)
184                         {
185                             // do nothing
186                         }
187                     }
188 
189                     this.selectedNode = newValue;
190                     this.UpdateComboBox(this.GetTreeNodeData(newValue));
191                 }
192             }
193         }
194 
195         protected virtual void OnDropDownClosed(object sender, ToolStripDropDownClosedEventArgs e)
196         {
197             if (null == this.toBeSelected)
198             {
199                 var selectedNode = this.treeView.SelectedNode;
200                 this.WhenTreeNodeChanged(selectedNode);
201             }
202         }
203 
204         protected virtual void UpdateComboBox(T data)
205         {
206             base.DisplayMember = this.DisplayMember; // update DisplayMember
207             if (null != data)
208             {
209                 this.DataSource = new List<T>() { data };
210                 this.SelectedIndex = 0;
211             }
212             else
213             {
214                 this.DataSource = null;
215             }
216         }
217 
218         protected virtual void WhenAfterExpand(object sender, TreeViewEventArgs e)
219         {
220             if (null != this.toBeSelected)
221             {
222                 if (this.SelectChildNode(e.Node.Nodes, this.toBeSelected))
223                 {
224                     this.toBeSelected = null;
225                 }
226             }
227         }
228 
229         protected virtual void WhenComboboxSizeChanged(object sender, EventArgs e)
230         {
231             this.DropDownWidth = base.Width;
232         }
233 
234         public virtual bool SelectChildNode(TreeNodeCollection nodes, T data)
235         {
236             var node = this.FindChildNode(nodes, data);
237             if (null != node)
238             {
239                 this.DoSelectTreeNode(node);
240                 return true;
241             }
242             else
243             {
244                 return false;
245             }
246         }
247 
248         protected abstract bool Identical(T x, T y);
249 
250         protected virtual void DoSelectTreeNode(TreeNode node)
251         {
252             this.SelectedNode = node;
253             this.ExpandTreeNode(node.Parent);
254         }
255 
256         public virtual TreeNode FindChildNode(TreeNodeCollection nodes, T data)
257         {
258             foreach (TreeNode node in nodes)
259             {
260                 var nodeData = https://www.cnblogs.com/yitouniu/p/this.GetTreeNodeData(node);
261                 if (this.Identical(nodeData, data))
262                 {
263                     return node;
264                 }
265             }
266 
267             return null;
268         }
269 
270         public virtual void ExpandTreeNode(TreeNode node)
271         {
272             if (null != node)
273             {
274                 node.Expand();
275                 this.ExpandTreeNode(node.Parent);
276             }
277         }
278 
279         public abstract T GetTreeNodeData(TreeNode node);
280     }
281 }

 

完整專案下載

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/123947.html

標籤:C#

上一篇:MD5加密實作方法

下一篇:Winform中實作ZedGraph不顯示y=0這條刻度線

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more