65.9K
CodeProject 正在变化。 阅读更多。
Home

C# 中的数据绑定 TreeView

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (80投票s)

2004年8月4日

5分钟阅读

viewsIcon

824122

downloadIcon

41010

C# 实现数据绑定 TreeView。

Sample Image

引言

这是 C# 实现的数据绑定 TreeView 控件。它可以将常规的 TreeView 控件与多个表绑定,并显示分层数据。

背景

当我在 C# 中搜索此类数据绑定 TreeView 时,除了 MSDN 上发布的一个 VB.NET 版本外,我没有找到任何其他版本。我决定将其转换为 Visual C#。原始文章和代码由 MSDN 的 Duncan Mackenzie 编写,可以在 此处链接 找到。在转换过程中,我发现原始代码过于复杂。因此,我做了一些更改来简化控件本身,并使其更容易使用。

控件

虽然我不是该控件的原创作者,但我希望将其介绍给所有 C# 开发者,因为我发现它是一个非常有用且易于使用的树视图控件。TreeView 控件可以绑定到任何支持 IListIListSource 的数据源。它使用 CurrencyManager 对象来访问绑定的数据源。CurrencyManager 还可以确保绑定到同一数据源的多个控件保持在数据源的同一项上。在演示示例中(大部分是从原始示例转换而来),当您单击树节点时,右侧面板会显示与 TreeView 控件绑定到同一数据源的相关数据。

Sample Image

Using the Code

在演示中,数据是从四个 Microsoft Access 表中检索的。

Data Tables

将数据检索到 DataView 对象后,可以使用其 DisplayMemberValueMemberDataSource 成员属性将其绑定到 TreeView 控件,如下所示:

    this.myTree.DisplayMember = “title”;
    this.myTree.ValueMember   = “title_id”;
    this.myTree.DataSource    = this.myDataView;

到目前为止,TreeView 控件中的数据以平面模式绑定到表。它只显示图书标题,如下所示:

Book Titles

为了以分层方式显示数据,需要对数据进行排序和分组。从上面的数据表中,我们可以看到数据可以按 **Publisher**、**Author**、**Title** 或它们的组合进行分组。为了显示如开头所示的分层数据,需要添加以下代码来进行排序和分组:

    this.myDataView.Sort = “pub_id, au_id, title_id”;
    this.myTree.AddGroup ("Publisher", "pub_id", "pub_name", "pub_id", 0, 0);
    this.myTree.AddGroup ("Author", "au_id", "au_name", "au_id", 1, 3);

它首先按 **Publisher** 分组数据,然后按 **Author** 分组。树中的 **publisher** 和 **author** 节点都是组节点,而 **book title** 节点是叶子节点。每个节点都带有一个 Value 成员,该成员可以是用于标识它们的 ID。在这种情况下,Value 成员是 pub_idau_idtitle_id

在演示项目中,我添加了一个菜单来显示如何更改组。可以通过选中菜单项来添加组,通过取消选中菜单项来删除组。以下示例按 **Author** 和 **Title** 对数据进行分组,并将 **publishers** 作为叶子节点。

Data Tables

虽然您不需要为叶子节点添加组,但您需要让树知道应该使用哪个数据组作为叶子节点。例如,如果数据仅按 **Publisher** 分组,那么叶子节点是 **authors** 还是 **book titles**?出于这个原因,我在 TreeView 控件中添加了一个名为 SetLeafData() 的方法。您可以通过控件的成员属性(如 DisplayMenmberValueMemberImageIndex 等)设置所有叶子节点数据。此方法只是一种一次性完成所有操作的简单方法。它还为叶子组分配了一个名称,这在从节点检索数据时很有用。

此控件包含有用的函数,可让您轻松地从节点检索数据。其 FindNodeByValue() 方法允许您通过其值查找叶子节点。例如,如果 **book titles** 是叶子节点,并且 title_id 是节点的 value member,输入一个 title ID 将自动选择具有该 ID 的图书。该控件的 FindNodeByPosition() 方法允许您通过数据源中的行索引查找叶子节点。

对原始代码进行的更改

除了前面提到的内容之外,主要的更改是将两个派生的 TreeNode 类合并为一个:dbTreeNode,并添加了一个名为 IsLeafNode() 的方法。dbTreeNode 类除了常规的 TreeNode 类外,还包含以下属性:

    public String GroupName;  // the name of the group
    public object Value;      // the value member to identify the node
    public object Item;       // the data row in the data source
    public int    Position;   // the row index in the data source

此更改的结果是消除了控件和使用控件的代码中的以下类、方法和事件:

    // In the control:
        Classes:   TreeGroupNode
              TreeLeavNode
              GroupTreeViewEventArgs
              GroupTreeViewCancelEventArgs
              LeafTreeViewEventArgs
              LeafTreeViewCancelEventArgs

        Methods:   FindFirstLeafNode()
              OnBeforeSelect()
              OnAfterSelect()
              currcyManager_PositionChanged()

        Events:      public delegate void BeforeGroupSelHandler()
              public event BeforeGroupSelHandler BeforeGroupSelect;
              public delegate void AfterGroupSelHandler()
              public event AfterGroupSelHandler AfterGroupSelect;
              public delegate void BeforeLeafSelHandler()
              public event BeforeLeafSelHandler BeforeLeafSelect;
              public delegate void AfterLeafSelHandler()
              public event AfterLeafSelHandler AfterLeafSelect;

        Event Handlers:
              private void currcyManager_PositionChanged()
    
     // In the code using the control:
        Event Handlers:
              private void myTree_BeforeGroupSelect()
              private void myTree_AfterGroupSelect()
              private void myTree_BeforeLeafSelect()
              private void myTree_AfterLeafSelect()

另一个更改是增加了禁用控件自动生成器功能的能力。在原始控件中,每当分配数据源、添加组或删除组时,都会生成或重新生成树。要显示如开头所示的三级分层树,树会生成 3 次。只有最后一次才能生成所需的结果。对于大量数据,这会减慢过程,因此我添加了一个 AutoBuilder 属性来允许禁用此功能。一旦禁用了自动生成功能,您需要显式调用 BuildTree() 函数,如下所示:

    this.bookDataView.Sort = "pub_id, au_name, title_id";
    this.myTree.DataSource = this.bookDataView;
    this.myTree.AddGroup ("Publisher", "pub_id","pub_name", "pub_id", 0,0);
    this.myTree.AddGroup ("Author", "au_id", "au_name", "au_id", 1, 3);
    this.myTree.SetLeafData ("Title", "title", "title_id", 2, 2);
    this.myTree.BuildTree();

结论

我希望这是一个有用的树视图控件。功劳应该归于 MSDN 的原创作者 Duncan Mackenzie。正如他在原始文章中所说:

“本文所示的数据绑定 Tree 控件将不是每个需要 Tree 控件来显示数据库信息的项目的答案,但它确实说明了您可以根据自己的目的自定义此控件的一种方法。请记住,本控件中的大部分代码在您希望构建的任何复杂数据绑定控件中基本相同,并且您可以利用现有的工作来使将来的控件开发更容易。”

再次强调,原始代码和文章可以在 此处链接 找到。当您阅读原始文章时,请注意,某些部分可能不适用于此 C# 实现,因为许多代码已被删除。我希望我的修改在不丢失功能的情况下简化了原始代码,并且它将使 C# 用户受益。

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.