现在的位置: 首页 > 综合 > 正文

Advanced TreeView for .NET

2014年03月03日 ⁄ 综合 ⁄ 共 5603字 ⁄ 字号 评论关闭
文章目录

TreeViewAdv in Multi-Column mode

Introduction

Working on several different projects, I was needed to display and edit hierarchical data. Of course, the first thing you will do is to use the standard .NET TreeView control. It works pretty well if you only need basic features. But learning this control to do something more complex is not an easy job. I could not find an alternative TreeView control which is free and fully meets my needs, so finally I decided to write my own.

The architecture of this control comes mainly from the Java Swing component, with some modifications. These are the key features of the TreeViewAdv control:

  • Model-View architecture - Will be covered in a separate section of this article.
  • Multiselection - Maybe the first limitation which you will find in the standard TreeView is that it’s not possible to select more then one node.
  • Unlimited number of controls for each node - You can display three icons + a CheckBox + two Labels.
  • Multicolumns - You can split the TreeView into several columns.
  • Load on Demand - Lazy load of child nodes.
  • Drag & Drop highlighting - Dynamically highlight the drop position.
  • 100% pure .NET code - No WinAPI is used in this control.

The following screenshots illustrate the TreeViewAdv features:

Drag&Drop highlighting

Multiselection

Using ComboBox to edit node

Model-View Architecture

I really like the Model-View pattern, and decided to use it in this control. The main idea of this pattern is to split the model (business object) from its visualization (control). If the model changes, it notifies the view by firing corresponding events. The view asks the model for details, if needed, and displays the changes. The model is described by ITreeModelInterface:

<span class="cs-keyword">public</span> <span class="cs-keyword">interface</span> ITreeModel
{
    IEnumerable GetChildren(TreePath treePath);
    <span class="cs-keyword">bool</span> IsLeaf(TreePath treePath);
 
    <span class="cs-keyword">event</span> EventHandler&lt;TreeModelEventArgs&gt; NodesChanged; 
    <span class="cs-keyword">event</span> EventHandler&lt;TreeModelEventArgs&gt; NodesInserted;
    <span class="cs-keyword">event</span> EventHandler&lt;TreeModelEventArgs&gt; NodesRemoved; 
    <span class="cs-keyword">event</span> EventHandler&lt;TreePathEventArgs&gt; StructureChanged;
}

It’s very simple, and you need to implement only two methods. GetChildren should return the list of child nodes of the specified parent (empty for root nodes). IsLeaf method tells TreeView whether it should try to read child nodes of the specified parent. If you wish TreeView to dynamically track model changes, you need to use one of several events of the ITreeModel interface. The most common is the StructureChanged event, which cause the TreeView to fully refresh the specified node (or empty, for the whole model). For example, see the default implementation of the ITreeModel interface – the TreeModel class.

To specify the exact node in the model, TreePath class is used. It stores the path from the root to the node, in the FullPath property.

<span class="cs-keyword">public</span> <span class="cs-keyword">class</span> TreePath
{
    <span class="cs-keyword">public</span> <span class="cs-keyword">object</span>[] FullPath{ <span class="cs-keyword">get</span>; }
    <span class="cs-keyword">public</span> <span class="cs-keyword">object</span> LastNode{ <span class="cs-keyword">get</span>; }
    <span class="cs-keyword">public</span> <span class="cs-keyword">object</span> FirstNode{ <span class="cs-keyword">get</span>; }
}

Using TreeView

In the source code, you can find two examples of how to use TreeViewAdv. The simplest way is to use TreeModel. All you need is to populate it with data and display it in the view:

_model = <span class="cs-keyword">new</span> TreeModel();
_model.Nodes.Add(<span class="cs-keyword">new</span> Node(<span class="cpp-string">"Root"</span>));
_tree.Model = _model;

The Node class, which is used in TreeModel, contains only the ‘Text’ and ‘IsChecked’ properties. If you need additional properties, you can create an ancestor of the Node class and use it in TreeModel.

But to use the full power of the TreeViewAdv, you should create your own realization of the ITreeModel interface. See the folder browser presented in the source code, for an example.

Customizing TreeView

There are a number of properties which help to customize the look and behavior of the TreeView. The main ones are:

  • Model - Assign your model to this property to display it.
  • NodeControls - The collection of controls which will be used to visualize the model. You should provide at least one NodeControl in order to see the model.
  • LoadOnDemand - Read all child nodes at start-up or when the parent node expands.
  • SelectionMode - Single (no multi-selection), Multi, MultiSameParent (children of only one node can be selected).
  • UseColumns - Display data in columns or not.
  • Columns - The collection of columns. For each column, you can specify its header, width and alignment.

NodeControls

The standard TreeView can display only one icon, CheckBox, and Label for each node. In TreeViewAdv, you can use any number of NodeControl. All controls must inherit from the ‘NodeControl’ abstract class. Inherited classes should contain the code to draw the control and the code to respond on user actions – mouse and keyboard events.

NodeControl

This is the class diagram of all NodeControls provided by the library:

Class diagram

The BindableControl class provides a ‘DataPropertyName’ which is used in the control to read and write data to the node. All that you need is to specify the name of the property of your class.

Terms and Conditions

The TreeViewAdv control is provided as free software with open source code. You can use it in your applications if the original copyright is kept.

The latest version of TreeViewAdv is always available here. Please feel free to add your comments and suggestions in the forum there.


Andrey Gliznetsov

Click here to view Andrey Gliznetsov's online profile.

 Andrey Gliznetsov著Advanced TreeView for .NET

.NET中的高级树控件

[介绍]

大家都知道.NET中标准的TreeView有不少的缺陷,所以,本文将写一个高级的有更多功能的树状控件,以替代.NET库中的TreeView。

该控件结构中大部分功能实现于Javascript,我们称这个控件为TreeViewAdv控件,它包括的新特征有:

Model-View architecture :将会在另一篇文章中,说明。
Multiselection :多个节点选择
Unlimited number of controls for each node:不限制每个节点的控件数;比如,你可以在一个节点中显示3个icon、一个CheckBox、两个Label
Multicolumns:多列
Load on Demand :节点惰性加载,不在一开始载入全部的节点
Drag & Drop highlighting:动态高亮拖放的位置
100% pure .NET code :不用任何的API

[模型-视图构架]

我非常喜欢模型-视图构架(Model-View Architecture),然后决定在这个控件中使用这个设计模式。该模式主要的思想是把模型(业务对象)和它的实现(控件)分开。当模型改变的时候,触发对应的事件。本文的模型如下:

Code:

public interface ITreeModel
{
    IEnumerable GetChildren(TreePath treePath);
    bool IsLeaf(TreePath treePath);

    event EventHandler<TreeModelEventArgs> NodesChanged;
    event EventHandler<TreeModelEventArgs> NodesInserted;
    event EventHandler<TreeModelEventArgs> NodesRemoved;
    event EventHandler<TreePathEventArgs> StructureChanged;
}

非常简单,GetChildren 返回对应的子节点,IsLeaf 返回是否是叶子节点。当拖动等动作时,事件被触发。

下面的类TreePath用以获取树的路径:

Code:

public class TreePath
{
    public object[] FullPath{ get; }
    public object LastNode{ get; }
    public object FirstNode{ get; }
}

TreeView使用

在源代码中,你可以发现两个使用TreeViewAdv的例子。最简单的方法是使用TreeModel。你所要做的只是向Tree中填充数据,然后显示它。

Code:

_model = new TreeModel();
_model.Nodes.Add(new Node("Root"));
_tree.Model = _model;

如果,想使用它的完全的功能,你需要实现TreeViewAdv接口,看看代码中的folder browser,就会明白很多了。

抱歉!评论已关闭.