C# winform treeview
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# winform treeview相关的知识,希望对你有一定的参考价值。
如何在数据库中设计“部门表”(需要建立哪些字段),用C#语言使用treeview实现如下图所示界面:
你好:数据库中的字段为三个字段就够用:分别为id,name,parentid(存储对应的父级id)
我写了两个函数,你把参数传进去就可以了:
功能函数:
#region InitNode
/// <summary>
/// 初始化节点
/// </summary>
/// <param name="dt">要加载成树结构的数据源</param>
private void InitNode(DataTable dt)
DataRow[] drRoot = dt.Select("id='0'");
if (drRoot != null && drRoot.Length > 0)
TreeNode root = new TreeNode();
root.Text = drRoot[0]["name"].ToString();
root.Tag = drRoot[0];
this.treeView1.Nodes.Add(root);
this.BuildChild(drRoot[0], root, dt);
#endregion
#region BuildChild
/// <summary>
/// 加载子节点
/// </summary>
/// <param name="dr">父节点对应的行</param>
/// <param name="root">父节点</param>
/// <param name="dt">要加载成树结构的数据源</param>
private void BuildChild(DataRow dr, TreeNode root,DataTable dt)
if (dr == null || root == null) return;
DataRow[] drChilds = dt.Select("parentid='" + dr["id"] + "'");
if (drChilds != null || drChilds.Length > 0)
foreach (DataRow drChild in drChilds)
TreeNode node = new TreeNode();
node.Text = drChild["name"].ToString();
node.Tag = dr;
root.Nodes.Add(node);
this.BuildChild(drChild, node, dt);
#endregion
函数调用:
this.InitNode(this.GetData());
测试数据源:
#region GetData
/// <summary>
/// 测试数据源
/// </summary>
private DataTable GetData()
DataTable dt = new DataTable();
dt.Columns.Add("id");
dt.Columns.Add("name");
dt.Columns.Add("parentid");
dt.Rows.Add(new object[] "0", "中国南方集团有限公司","root");
dt.Rows.Add(new object[] "1", "集团办办公室", "0" );
dt.Rows.Add(new object[] "2", "人力资源部", "0" );
dt.Rows.Add(new object[] "3", "市场部", "0" );
dt.Rows.Add(new object[] "301", "市场部1", "3" );
dt.Rows.Add(new object[] "302", "市场部2", "3" );
dt.Rows.Add(new object[] "4", "B公司", "0" );
dt.Rows.Add(new object[] "401", "销售部", "4" );
dt.Rows.Add(new object[] "402", "质管部", "4" );
dt.Rows.Add(new object[] "5", "D公司", "0" );
dt.Rows.Add(new object[] "6", "A公司", "0" );
dt.Rows.Add(new object[] "7", "C公司", "0" );
dt.Rows.Add(new object[] "8", "网络信息中心", "0" );
return dt;
#endregion 参考技术A 这个表很简单,就像ls说的即可,关键是这个递归的sp不好写,我写过一个,但是是给oracle用的。或者你用xml文件去实现。 参考技术B 建立一个三个字段的表就够了
ID(varchar,4),Name(varchar,20),ParentID(varchar,4):
0100 中国南方集团有限公司 0000
0110 集团办公室 0100
......
0140 B公司 0100
0141 销售部 0140
......
需要TreeView的代码? 参考技术C protected void BindTree()
TreeNode node = new TreeNode(); //这里是创建一个根节点,就是图片中看到的Root
node.Text = "中国南方集团有限公司";
CreateChildTree(node, 0);
_tree_view.Nodes.Add(node);
protected void CreateChildTree(TreeNode _parentNode, int _parentID)
using (SqlConnection _conn = new SqlConnection(_connstr))
SqlCommand _comm = new SqlCommand();
string sql = "select * from company where rootid=@rootid";
_comm.Parameters.Add("@rootid", SqlDbType.Int).Value = _parentID;
_comm.CommandText = sql;
_comm.Connection = _conn;
_conn.Open();
using (SqlDataReader r = _comm.ExecuteReader())
while (r.Read())
TreeNode _node = new TreeNode(r["txt"].ToString());
CreateChildTree(_node, (int)r["ID"]); //递归出子节点
_parentNode.ChildNodes.Add(_node);
参考技术D 建立一个表就行了
格式
id 父id 名称
0 -1 中国南方集团有限公司 //最顶级节点
1 0 B公司 //说明B公司在中国南方集团有限公司下面
2 0 市场部 //市场部在中国南方集团有限公司下面
3 1 生产部 //生产部在B公司下面
然后再来个建树 就可以了
如果不会的话 liyangfd@163.com
在 C# winforms 应用程序中使用文本框过滤 Treeview
【中文标题】在 C# winforms 应用程序中使用文本框过滤 Treeview【英文标题】:Filter a Treeview with a Textbox in a C# winforms app 【发布时间】:2012-01-05 19:34:10 【问题描述】:我的 C# winform 中有一个 TreeView。我希望能够通过搜索框添加搜索功能。 基本上当用户输入字母时(我猜是 _TextChanged 事件),我只显示包含输入字母的子节点的节点...
我的 TreeView 包含 53 个父节点,总共超过 15000 个节点,所以我需要一些高性能的东西。我从加载到 DataTable 的 csv 构建 TreeView,然后进行查询以获取具有关联子节点的父节点...
更新
我有个主意。 最终目标是当用户双击子节点时,它会被添加到 listView。
我首先在一个简单的列表视图中实现了这个搜索功能,我没有将我的数据分类。
我的想法是,一旦用户开始输入内容,我就会关闭树视图并改为显示列表视图...
我会尝试并实施,看看它在性能方面有什么好处...欢迎任何对此想法的批评。
【问题讨论】:
15000 - 如果您在现代 PC 上运行,文本节点不会太多。你甚至可以过滤树,关键是要有一个聪明的策略来避免性能问题。我将尝试描述一个。列表的解决方案在技术上是可以的,但我猜不是预期的和最好的用户体验。 你试过暴力破解方法了吗?一个好的 ole foreach(ParentNode.ChildNodes 中的 TreeNode 节点)? 【参考方案1】:最后这就是我所做的,它符合我的要求。 我首先复制我的 TreeView 并存储到 fieldsTreeCache 中。然后我清除fieldsTree。然后我搜索缓存并将包含我的搜索参数的任何节点添加到 fieldsTree。请注意,一旦您搜索,您将不再拥有显示的父节点。您只需获得所有终端节点。我这样做是因为如果没有,我有 2 个选择:
展开所有包含匹配子节点的父节点,但速度很慢,并且一个父节点可能有 50 个子节点,这在视觉上不太好。不展开父节点,但您只获得类别而不是您正在搜索的子节点。
void fieldFilterTxtBx_TextChanged(object sender, EventArgs e)
//blocks repainting tree till all objects loaded
this.fieldsTree.BeginUpdate();
this.fieldsTree.Nodes.Clear();
if (this.fieldFilterTxtBx.Text != string.Empty)
foreach (TreeNode _parentNode in _fieldsTreeCache.Nodes)
foreach (TreeNode _childNode in _parentNode.Nodes)
if (_childNode.Text.StartsWith(this.fieldFilterTxtBx.Text))
this.fieldsTree.Nodes.Add((TreeNode)_childNode.Clone());
else
foreach (TreeNode _node in this._fieldsTreeCache.Nodes)
fieldsTree.Nodes.Add((TreeNode)_node.Clone());
//enables redrawing tree after all objects have been added
this.fieldsTree.EndUpdate();
【讨论】:
我也采用了这种方法,非常适合我的情况。 _treeTablesCache 是如何创建的? 如果我有一个具有多个节点级别的节点呢? @Thunder 你应该在表单类Form.Designer.cs
中定义它,就像这样private System.Windows.Forms.TreeView _fieldsTreeCache;
。在 Form 构造函数 this._fieldsTreeCache = new TreeView();
中启动它,并在添加或删除节点时填充它。或其他地方,如Form_Shown
【参考方案2】:
这里有一个简单的小例子(带有来自 msdn 的代码),它是一种过滤掉 TreeView 节点显示的非常简单的方法。
winforms 在树形视图中只能添加或删除 TreeNode。
如果将节点与它们的数据一起存储到字典中(使用唯一键),则仍然可以改进对节点的搜索。
using System.Collections;
using System.Windows.Forms;
namespace FilterWinFormsTreeview
// The basic Customer class.
public class Customer : System.Object
private string custName = "";
protected ArrayList custOrders = new ArrayList();
public Customer(string customername)
this.custName = customername;
public string CustomerName
get return this.custName;
set this.custName = value;
public ArrayList CustomerOrders
get return this.custOrders;
// End Customer class
// The basic customer Order class.
public class Order : System.Object
private string ordID = "";
public Order(string orderid)
this.ordID = orderid;
public string OrderID
get return this.ordID;
set this.ordID = value;
// End Order class
public static class TreeViewHelper
// Create a new ArrayList to hold the Customer objects.
private static ArrayList customerArray = new ArrayList();
public static void FilterTreeView(TreeView treeView1, string orderText)
if (string.IsNullOrEmpty(orderText))
FillMyTreeView(treeView1);
else
// Display a wait cursor while the TreeNodes are being created.
Cursor.Current = Cursors.WaitCursor;
// Suppress repainting the TreeView until all the objects have been created.
treeView1.BeginUpdate();
foreach (TreeNode customerNode in treeView1.Nodes)
var customer = customerNode.Tag as Customer;
if (customer != null)
customerNode.Nodes.Clear();
// Add a child treenode for each Order object in the current Customer object.
foreach (Order order in customer.CustomerOrders)
if (order.OrderID.Contains(orderText))
var orderNode = new TreeNode(customer.CustomerName + "." + order.OrderID);
customerNode.Nodes.Add(orderNode);
// Reset the cursor to the default for all controls.
Cursor.Current = Cursors.Default;
// Begin repainting the TreeView.
treeView1.EndUpdate();
public static void FillMyTreeView(TreeView treeView1)
// Add customers to the ArrayList of Customer objects.
if (customerArray.Count <= 0)
for (int x = 0; x < 1000; x++)
customerArray.Add(new Customer("Customer" + x.ToString()));
// Add orders to each Customer object in the ArrayList.
foreach (Customer customer1 in customerArray)
for (int y = 0; y < 15; y++)
customer1.CustomerOrders.Add(new Order("Order" + y.ToString()));
// Display a wait cursor while the TreeNodes are being created.
Cursor.Current = Cursors.WaitCursor;
// Suppress repainting the TreeView until all the objects have been created.
treeView1.BeginUpdate();
// Clear the TreeView each time the method is called.
treeView1.Nodes.Clear();
// Add a root TreeNode for each Customer object in the ArrayList.
foreach (Customer customer2 in customerArray)
var customerNode = new TreeNode(customer2.CustomerName);
customerNode.Tag = customer2;
treeView1.Nodes.Add(customerNode);
// Add a child treenode for each Order object in the current Customer object.
foreach (Order order1 in customer2.CustomerOrders)
var orderNode = new TreeNode(customer2.CustomerName + "." + order1.OrderID);
customerNode.Nodes.Add(orderNode);
// Reset the cursor to the default for all controls.
Cursor.Current = Cursors.Default;
// Begin repainting the TreeView.
treeView1.EndUpdate();
【讨论】:
with code from msdn
,链接在哪里? @punker76【参考方案3】:
TreeView
中的每个节点都有Expanded
和IsVisible
属性。同时可见的项目数量是有限的(TreeView.VisibleCount
)。根据这些信息,您可以显着减少要探测的节点数量。
扫描节点及其子节点时,您可以在折叠节点内找到第一个匹配项时中止递归,因此您已经知道它至少有一个子节点并且无论如何都是可见的。
李>异步执行过滤。 (例如使用new Task()
)在输入最少数量的字符后开始第一个任务(比如说3)。下一个键入的字符必须取消正在运行的任务并开始新的任务。
【讨论】:
以上是关于C# winform treeview的主要内容,如果未能解决你的问题,请参考以下文章