显示标题子项的一个层次化集合,并且每个子项都通过一个 TreeNode 而被呈现。
- 命名空间:System.Windows.Forms
- 汇编集:System.Windows.Forms(在 system.windows.forms.dll 中)
语法
[ComVisibleAttribute(true)] [ClassInterfaceAttribute(ClassInterfaceType.AutoDispatch)] public class TreeView : Control
备注
Nodes 集合保持了所有被指派给 TreeView 控件的 TreeNode 对象。该集合中的这些树节点都能够被引用成根树节点。任何后续被添加到当前根树节点中的树节点都被引用成一个子节点。因为每个 TreeNode 都能够包含其他 TreeNode 对象的集合,在你反复通过这个集合进行查找的时候,你可能难以检测你在树结构中的位置。因此你可以使用 PathSeparator 对 TreeNode.Fullpath 字符串进行分析来检测是否是一个 TreeNode 标签的开始部分与结束部分。
你可以通过为 ImageList 属性指派一个 ImageList 并且引用 ImageList 来为某个 Image 所指定的索引值来显示树节点的图片。你可以使用下列属性来指派图片:
- 把 ImageIndex 属性设置成你需要在树节点没有被选中的时候所显示的 Image 索引值。
- 把 SelectedImageIndex 属性设置成你需要在树节点被选中的时候所显示的 Image 索引值。
通过 ImageIndex 与 SelectedImageIndex 属性值而被引用的图片是被指派到 Nodes 集合中的所有树节点在默认时被显示的图片。另外,个别树节点能够通过设置 TreeNode.ImageIndex 与 TreeNode.SelectedImageIndex 属性来重载默认的图片。
树节点能够被展开来显示下级子树节点。用户能够通过单击加号(+)按钮来展开 TreeNode,如果至少有一个子树节点被显示在当前 TreeNode 的下面,或者你也可以通过调用 TreeNode.Expand 方法来展开 TreeNode。如果要展开 Nodes 集合中的所有级别的子树节点,可以调用 ExpandAll 方法。你可以通过调用 TreeNode.Collapse 方法来收缩下级子 TreeNode,或者用户能够单击头号(-)按钮,如果至少有一个子树节点被显示在当前 TreeNode 的下面。你同样可以调用 TreeNode.Toggle 方法在展开与收缩状态之间进行切换。
树节点能够有选择性地显示复选框。要显示复选框,就需要把 TreeView 的 CheckBoxes 属性设置成 true。Checked 属性被设置成 true 的树节点会自动显示成一个被选中的状态。
注意:在 BeforeCheck 或者 AfterCheck 事件中设置 TreeNode.Checked 属性能够导致这些事件多次被触发并且还会导致出现不可预料的行为。例如,你可能在递归更新子节点的时候,在事件处理器中设置 Checked 属性,而事实上用户并没有展开并且单独地对每一个子节点进行复选。要防止多次被触发的事件,你可以在事件处理器中添加只执行你的递归代码的逻辑,如果 TreeViewEventArgs 的 Action 属性没有被设置成 TreeViewAction.Unknown,相关范例,请参考 AfterCheck 事件或者 BeforeCheck 事件的[范例]部分。
你可以通过设置一些显示属性与样式属性来改变 TreeView 控件的外观。把 ShowPlusMinus 设置成 true 会分别在每个能够被展开或者被收缩的 TreeNode 中显示一个加号按钮或者减号按钮。把 ShowRootLines 属性设置成 true 会导致 TreeView 显示所有根树节点之间的连接线。你可以把 ShowLines 属性设置成 true 来显示子树节点到它们的根节点之间的连接线。把 HotTracking 属性设置成 true 会在鼠标指针经过的时候改变树节点的标签外观。在热点被追踪到的时候,树节点的标签外观就会变成超级链接的形式。你同样可以完全定制 TreeView 控件的外观。要这样做,就需要把 DrawMode 属性设置成除了 TreeViewDrawMode.Normal 之外的任何值,并且处理 DrawNode 事件。
提示:在运行时设置 CheckBoxes、Scrollable、ImageIndex,以及 SelectedImageIndex 属性的时候,会重建(请参考:[Control.RecreateHandle])TreeView 的处理来更新控件的外观。这将导致所有的树节点都被收缩,但是除了被选中的 TreeNode 之外。
范例
下列代码范例示范了 TreeView 控件的使用。
// 以范例节点来组装 TreeView 控件。 private void InitializeTreeView() { treeView1.BeginUpdate(); treeView1.Nodes.Add("Parent"); treeView1.Nodes[0].Nodes.Add("Child 1"); treeView1.Nodes[0].Nodes.Add("Child 2"); treeView1.Nodes[0].Nodes[1].Nodes.Add("Grandchild"); treeView1.Nodes[0].Nodes[1].Nodes[0].Nodes.Add("Great Grandchild"); treeView1.EndUpdate(); }
下面所示的更复杂的代码范例显示了 TreeView 控件中的自定义信息。根树节点显示了客户的名称,并且子树节点显示了被指派给每个客户的序列数字。在这个范例中,1,000 个客户平均按照每客户 15 个订单的规律而被显示。TreeView 的重绘通过使用 BeginUpdate 与 EndUpdate 方法而被抑制,并且在 TreeView 创建并且绘制 TreeNode 对象的时候还会显示一个表示等待的 Cursor。这个范例需要你拥有能够保持 Order 对象集合的 Customer 对象。另外同样需要你在 Form 中创建了 TreeView 控件实例的应用程序的目录中拥有一个名为 MyWait.cur 的鼠标指针文件。
// 创建新的 ArrayList 来保持 Customer 对象。 private ArrayList customerArray = new ArrayList(); private void FillMyTreeView() { // 把客户添加到 Customer 对象的 ArrayList 中。 for(int x=0; x<1000; x++) { customerArray.Add(new Customer("Customer" + x.ToString())); } // 在 Customer 对象的 ArrayList 中添加订单。 foreach(Customer customer1 in customerArray) { for(int y=0; y<15; y++) { customer1.CustomerOrders.Add(new Order("Order" + y.ToString())); } } // 在 TreeNode 被创建之前显示表示等待的鼠标指针。 Cursor.Current = new Cursor("MyWait.cur"); // 抑制 TreeView 的重绘直到所有的对象全部被创建完毕。 treeView1.BeginUpdate(); // 在每次调用这个方法的时候清除 TreeView 的内容。 treeView1.Nodes.Clear(); // 在每个 Customer 对象的 ArrayList 中添加一个根 TreeNode。 foreach(Customer customer2 in customerArray) { treeView1.Nodes.Add(new TreeNode(customer2.CustomerName)); // 在当前 Customer 的每个 Order 对象中添加子树节点。 foreach(Order order1 in customer2.CustomerOrders) { treeView1.Nodes[customerArray.IndexOf(customer2)].Nodes.Add( new TreeNode(customer2.CustomerName + "." + order1.OrderID)); } } // 把鼠标指针重围成所有控件的默认状态。 Cursor.Current = Cursors.Default; // 开始重绘 TreeView。 treeView1.EndUpdate(); }
继承层次
System.Object System.MarshalByRefObject System.ComponentModel.Component System.Windows.Forms.Control System.Windows.Forms.TreeView System.ComponentModel.Design.ObjectSelectorEditor.Selector
线程安全
这个类型的任何公开的静态(在 Visual Basic 中是 Shared)成员都是线程安全的。任何实例成员都不能够保证是线程安全的。