日期:2012-02-04  浏览次数:20535 次

Windows 窗体控件开发示例
Duncan Mackenzie
Microsoft Developer Network
2002 年 5 月

摘要:讲述了如何向 TreeView 控件添加数据绑定功能,它是一系列 Microsoft Windows 控件开发示例之一。您可以将本文与相关的概述文章结合起来阅读。
您可以从 MSDN Code Center 下载 WinFormControls.exe(英文)源代码。(请注意,在示例文件中,程序员的注释使用的是英文,本文中将其译为中文是为了便于读者理解。)
本文是介绍如何在 Microsoft® .NET 中开发控件的系列文章中的第四篇(共五篇):
  • Developing Custom Windows Controls Using Visual Basic .NET (overview)(英文)
  • Adding Regular Expression Validation(英文)
  • Combining Multiple Controls into One(英文)
  • 扩展 TreeView 控件
  • Drawing Your Own Controls Using GDI+(英文)

目录

  • 简介
  • 设计数据绑定树视图
  • 实现数据绑定
  • 使用 CurrencyManager 对象
  • 将 DataSource 转变为树
  • 示例应用程序
  • 小结

简介


在可能的情况下,您应该先使用些现成的控件;因为提供的 Microsoft® Windows® 窗体控件中包含大量编码和测试成果,如果您要放弃它们从头开始,无疑是一种巨大的浪费。基于此,在本例中,我将继承一个现有 Windows 窗体控件 TreeView ,然后对其进行自定义。在下载该 TreeView 控件的代码时,您还会得到附加的控件开发示例,以及一个演示如何与其他数据绑定控件一起使用该增强 TreeView 的示例应用程序。

设计数据绑定树视图


对于 Windows 开发人员来说,向 TreeView 控件添加数据绑定是经常会遇到的问题,但由于 TreeView 和其他控件(如 ListBoxDataGrid)存在一个主要差别(即 TreeView 显示分层数据),因而基本控件目前还不支持此功能(也就是说,我们还必须使用它)。给定一个数据表,您就会很清楚如何在 ListBoxDataGrid 中显示该信息,但利用 TreeView 的分层特点来显示同样的数据就不那么简单明了。就个人而言,我在使用 TreeView 显示数据时曾应用过许多不同的方法,但有一种方法最常用:按某些字段将表中的数据分组,如图 1 所示。

图 1:在 TreeView 中显示数据
在本例中,我将创建一个 TreeView 控件,在该控件中可传递一个平面数据集(如图 2 所示),并可轻松地生成图 1 所示的结果。

图 2:平面结果集,包含创建图 1 所示的树所需的所有信息
在开始编码之前,我为新控件想出了一个可以处理该特定数据集的设计,并希望它能够适用于许多其他类似的情形。添加一个足可以使用大多数平面数据创建分层结构的组集合,在该集合中为每一级分层均指定一个分组字段、显示字段和值字段(任一或所有字段均应相同)。为了将图 2 所示的数据转变成图 1 所示的 TreeView,我的新控件要求您定义两个分组级别 Publisher 和 Title,并将 pub_id 定义为 Publisher 组的分组字段,将 title_id 定义为 Title 组的分组字段。除分组字段以外,还需要为每个组指定显示和值字段,以确定在相应组节点上显示的文本以及用来唯一标识特定组的值。当遇到此类数据时,请使用 pub_name/pub_idtitle/title_id 作为这两个组的显示/值字段。作者信息将变成树的叶节点(分组分层结构末端的节点),您还需要为这些节点指定 ID (au_id) 和显示 (au_lname) 字段。
构建自定义控件时,在开始编码之前确定程序员对该控件的使用方法将有助于提高控件的使用效率。这种情况下,我希望程序员(在给定了前面所示的数据和所需结果的情况下)能够使用如下几行代码完成分组:
        With DbTreeControl            .ValueMember = "au_id"            .DisplayMember = "au_lname"            .DataSource = myDataTable.DefaultView            .AddGroup("Publisher", "pub_id", "pub_name", "pub_id")            .AddGroup("Title", "title_id", "title", "title_id")        End With
注意:这并不是我最终编写的代码行,但两者相差不多。在开发控件的过程中,我意识到需要将与 TreeView 关联的 ImageList 中的图像索引与每个分组级别相关联,因此必须向 AddGroup 方法中额外添加一个参数。

为了真正构建该树,我将浏览数据并查找字段(指定为每个分组的分组值)的更改,同时在必要时创建新分组节点,并针对每个数据项创建一个叶节点。由于存在分组节点,因此总节点数将大于数据源中的项目数,但基础数据中的每个项有且仅有一个叶节点。

图 3:分组节点与叶节点
叶节点和分组节点之间的区别(如图 3 所示)对本文的余下部分具有重要意义。我决定将这两类节点区别对待,为每一类节点分别创建自定义节点,并根据所选的节点类型引发不同的事件。

实现数据绑定


为该控件编写代码的第一步是创建项目和相应的起始类。在本例中,我首先创建一个新 Windows 控件库,然后删除默认的 UserControl 类,并用一个从 TreeView 控件继承的新类来代替它:
Public Class dbTreeControl    Inherits System.Windows.Forms.TreeView

从这时起,我将设计一个可以放入到窗体中的控件,并使其具有常规的 TreeView 的外观和功能。下一步是开始添加旨在处理在 TreeView 中加入的新功能所需的代码,即数据绑定和分组数据。