TreeView控件
一、TreeView控件使用
TreeView控件用来显示信息的分级视图,如同Windows里的资源管理器的目录。TreeView控件中的各项信息都有一个与之相关的Node对象。TreeView显示Node对象的分层目录结构,每个Node对象均由一个Label对象和其相关的位图组成。在建立TreeView控件后,我们可以展开和折叠、显示或隐藏其中的节点。TreeView控件一般用来显示文件和目录结构、文档中的类层次、索引中的层次和其他具有分层目录结构的信息。
下面是一些常用的方法和属性:
添加节点
TreeNode tn1 = new TreeNode(textBox1.Text.Trim()); tn1.Name = textBox1.Text.Trim(); treeView1.SelectedNode.Nodes.Add(tn1);
编辑选中节点
只有当 TreeView 的 LabelEdit 属性设置为 true,此方法才生效。 如果 LabelEdit 设置为 false,将引发异常,并且树节点不会进入可编辑状态。与之对应的是EndEdit()方法来关闭编辑节点。
treeView1.LabelEdit = true; treeView1.SelectedNode.BeginEdit();
删除选中节点
treeView1.Nodes.Remove(treeView1.SelectedNode);
展开选中节点
treeView1.SelectedNode.ExpandAll();
折叠选中节点
方法传递的布尔参数为 true 则使子节点保持当前状态;为 false 则折叠子节点。
treeView1.SelectedNode.Collapse(false);
选中节点折叠展开状态切换
treeView1.SelectedNode.Toggle();
显示复选框
与之相关联的是Checked属性获取或设置一个值,用以指示树节点是否处于选中状态。
treeView1.CheckBoxes = true;
选中节点路径
treeView1.SelectedNode.FullPath
选中节点树深度
treeView1.SelectedNode.Level;
树节点数目
treeView1.GetNodeCount(true);
详细使用可以参考MSDN:http://msdn.microsoft.com/zh-cn/library/system.windows.forms.treenode(v=vs.100).aspx
实例1.TreeView控件显示本地磁盘、文件夹
遍历磁盘代码:
//来源:http://zxlovenet.cnblogs.com private void ForeachDisk() { DriveInfo[] dr = DriveInfo.GetDrives(); string driveName = ""; foreach (DriveInfo d in dr) { switch (d.DriveType) { case DriveType.Fixed: driveName = "本地磁盘(" + d.Name.Substring(0, 2) + ")"; break; case DriveType.Removable: driveName = "可移动磁盘(" + d.Name.Substring(0, 2) + ")"; break; case DriveType.CDRom: driveName = "DVD驱动器(" + d.Name.Substring(0, 2) + ")"; break; case DriveType.Network: driveName = "网络驱动器(" + d.Name.Substring(0, 2) + ")"; break; default: driveName = "未知(" + d.Name + ")"; break; } this.treeView1.Nodes.Add(d.Name, driveName); } }
显示文件夹内容:
//来源:http://zxlovenet.cnblogs.com private void ReadDir(TreeNodeMouseClickEventArgs e) { if (e.Node.Nodes.Count > 0) { if (e.Node.IsExpanded) { e.Node.Collapse(); } else { e.Node.Expand(); } } else { if (Directory.Exists(e.Node.Name)) { try { string[] allDirectory = Directory.GetDirectories(e.Node.Name); foreach (string s in allDirectory) { e.Node.Nodes.Add(s, s.Remove(0, s.LastIndexOf("//") + 1)); } listBox1.Items.Clear(); string[] allFiles = Directory.GetFiles(e.Node.Name); foreach (string sf in allFiles) { listBox1.Items.Add(sf.Remove(0, sf.LastIndexOf("//") + 1)); } } catch { } } e.Node.Expand(); } }
实例2.TreeView实现拖拽操作
后台代码:
//来源:http://zxlovenet.cnblogs.com private Point Position = new Point(0, 0); private void Form1_Load(object sender, EventArgs e) { this.treeView1.AllowDrop = true; this.treeView1.ExpandAll(); } private void treeView1_ItemDrag(object sender, ItemDragEventArgs e) { DoDragDrop(e.Item, DragDropEffects.Move); } private void treeView1_DragEnter(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(typeof(TreeNode))) e.Effect = DragDropEffects.Move; else e.Effect = DragDropEffects.None; } private void treeView1_DragDrop(object sender, DragEventArgs e) { TreeNode myNode = null; if (e.Data.GetDataPresent(typeof(TreeNode))) { myNode = (TreeNode)(e.Data.GetData(typeof(TreeNode))); } else { MessageBox.Show("error"); } Position.X = e.X; Position.Y = e.Y; Position = treeView1.PointToClient(Position); TreeNode DropNode = this.treeView1.GetNodeAt(Position); // 1.目标节点不是空。2.目标节点不是被拖拽接点的字节点。3.目标节点不是被拖拽节点本身 if (DropNode != null && DropNode.Parent != myNode && DropNode != myNode) { TreeNode DragNode = myNode; // 将被拖拽节点从原来位置删除。 myNode.Remove(); // 在目标节点下增加被拖拽节点 DropNode.Nodes.Add(DragNode); } // 如果目标节点不存在,即拖拽的位置不存在节点,那么就将被拖拽节点放在根节点之下 if (DropNode == null) { TreeNode DragNode = myNode; myNode.Remove(); treeView1.Nodes.Add(DragNode); } }
二、C# TreeView控件中的nodemouseclick事件
nodemouseclick有两种响应
1:响应单击扩展符"+" 如果不想对该扩展符响应,利用一个判断语句即可解决,代码如下
private void tvMain_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.Node.Bounds.Contains(e.Location)) {
//将树节点展开或折叠 treeview1.SelectedNode.Toggle();
//选中节点时,图标为默认未选中时的图标
e.Node.SelectedImageIndex = e.Node.ImageIndex; } }
2:响应单击节点事件
可是每当单击时并不是自己想要的结果,要不是第一次点击没有反应,就是点击这个节点却响应了上次单击要出现的结果,或者是要双击才可响应,解决方法,代码如下:
private void tvMain_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { tvMain.SelectedNode = e.Node; //一定要先指定e.node,否则不能正确运行 }
三、设置父节点和子及节点的图标
动态生成一个树形目录后,想在每个节点前添加图标。
添加之前先判断,这个节点是否有子节点,如果有则添加一种图标,如果没有,则添加另外一种图标。用递归实现,当然TreeView的第一层子节点只有一个,作为整棵树的根节点的时候,这个代码比较有效,否则的话,就要来一次遍历了。
SetIcon(treeview1.Nodes[0]); private void SetIcon(TreeNode tn) { foreach (TreeNode node in tn.Nodes) { if (node.Nodes.Count > 0) { node.ImageIndex = 0; SetIcon(node); } else { node.ImageIndex = 2; } } }
如果一级节点有很多的话,遍历所有节点。
SetIcon(tvPM.Nodes); private void SetIcon(TreeNodeCollection nodes) { foreach (TreeNode node in nodes) { if (node.Nodes.Count > 0) { node.ImageIndex = 0; SetIcon(node.Nodes); } else { node.ImageIndex = 2; } } }
四、动态刷新TreeNode节点的图标
实现类似于windows XP资源管理器中的树形列表中的,点击加号,可以展开文件夹的同时,对应节点的图标也变成打开的文件夹的图标。
功能上,节点的展开Expand和闭合Collapse已经实现,现在需要实现对应打开的文件夹图标和关闭的文件夹图标的动态更新。
private void tvMain_AfterExpand(object sender, TreeViewEventArgs e) { e.Node.ImageIndex = 1; e.Node.SelectedImageIndex = 1; }
private void tvMain_AfterCollapse(object sender, TreeViewEventArgs e) { e.Node.ImageIndex = 0; e.Node.SelectedImageIndex = 0; }
效果如图:
文件夹未展开时候的状态:
文件夹展开时候的状态:
对于TreeView中的TreeNode,对应的图标,是分选中时候的SelectedImageIndex,和未选中时候的ImageIndex。
在改为自己要的图标的时候,千万记得别忘了都要考虑进去,而别只用了一个,忽略了另外一个。