用于显示分层数据的嵌套网格(from msdn)

数据|显示

在“前沿技术”的 2003 年 8 月刊,我讨论了如何扩展 ASP.NET DataGrid 服务器控件,以便将多表数据容器(如 DataSet 对象)用作其数据源。 如果 DataSet 包含数对相关表,则只要所显示的表是其中某个关系的父级,该控件就将添加动态创建的按钮列。 当单击此列按钮时,将显示子 DataGrid,并将根据此关系列出选定记录的子行。 总体行为显示在图 1 中,此行为与 Windows 窗体 DataGrid 控件在类似情形下的工作方式相同。

图 1 父级和子级 DataGrids

图 1 中显示的应用程序是包含两个一起工作的 DataGrid 控件的用户控件。 该用户控件(请参阅 2003 年 8 月的源代码)包含使两个网格保持同步所需的全部逻辑。 父 DataGrid 绑定到 DataSet 并显示父表的内容。 当这一情况发生时,该用户控件确保 DataSet(所显示的表在其中充当父级)内部存在关系。 子 DataGrid 绑定到数据视图,该视图包含仅仅与选定记录相关的子表中的所有记录。 因此,如果您有一个 DataSet,并且它有两个已建立关系的表,那么该用户控件将为您节省时间,因为您不需要针对任何额外的显示机制来编写代码。

那么这种方法有什么问题呢? 如果您仅仅关注基本功能,那么它没有问题。 但是,一些读者已注意到不使用两个物理上分隔的 DataGrid 控件也许会更好。 该用户控件在组成控件的周围构建了一个壁垒,从而使您只能通过映射属性和方法或者通过公开整个内部控件来访问这些组成控件。 从可编程性的观点来看,使用一个 DataGrid 控件来显示分层数据要简单得多。 首先,您不必担心父表的配置问题。 只需使用 DataGrid 控件的标准接口即可。 显示相关数据的任何子网格都可以动态创建,并可以显示在主网络的布局内部。

图 2 嵌入式子 DataGrid

另一方面,需要提醒的是,设计 DataGrid 控件不是为了包含分层数据。 其内部布局最适合显示表格式数据。 DataList 控件可能是一个不错的选择,但它不提供固有的分页支持,并且需要一些代码才能像 DataGrid 一样工作。 当在 Google 上快速搜索“嵌套 DataGrid”时,返回了讨论如何将 DataGrid 嵌入到 DataList 控件的文章的链接,这些文章给了我关于本专栏的一些启示。 这里,我将构造一个从 DataGrid 类继承的自定义控件。 该控件实现一个自定义列类型 (ExpandCommandColumn),并包含显示与被单击的项关联的记录所需的全部逻辑。 展开视图通过嵌入到父级中的子 DataGrid 表示。 图 2 显示了此控件的外观。

构造嵌套网格

只有当数据源是包含表之间的关系的 DataSet 对象时,分层的 DataGrid 控件才有意义。 例如,假定某个 DataSet 具有 Customers 表和 Orders 表,并在 CustomerID 列上建立了这两个表之间的 DataRelation。 只要 DataGrid 包含按钮列,那么当您单击它时就能够为选定的客户创建一个子视图,并将所生成的 DataView 对象绑定到子网格。

由于新控件(在示例代码中称为 NestedGrid)是从 DataGrid 类继承的,因此可以在适合使用 DataGrid 对象的任何情况下使用它。 但是,最后这一句还有待修饰。 通常,当从基类派生控件时,可能存在这样的情况:所派生的控件由于其特定的扩展和附加项而无法替换原始控件。 在本专栏中,我不会花太多的时间来使 NestedGrid 组件向后兼容基 DataGrid 类。 为了简单起见,我假设您始终将它绑定到 DataSet 对象。

关于 NestedGrid 控件,还有其他几个假设,这将在后面的部分逐渐说明。 特别要说明的是,由您负责添加规定每一行的 expanded/collapsed 状态的按钮列。 从理论上来讲,该列可以放在网格中的任何位置。 但是,我在这里假设展开列是网格中的第一列。 (2003 年 8 月刊已讨论,可以适当地修改行为,以便只有当 DataGrid 绑定到具有相关表的 DataSet 时才动态生成该列。)

如果您有过一点使用 DataGrid 控件的经验,会知道尽管它功能极其强大,可自定义性也非常强,但它无法很好地支持布局的变化。 网格布局表示表格式数据 — 按规则连续的若干个大小相等的行。 怎样才能嵌入具有此限制的子网格呢?

这里要提醒的重要一点是,网格是作为标准的 HTML 表呈现的。 一旦单元格形成了规则的表布局,就可以在其中的每个单元格中放入任何内容,其中包括表示子网格的子表(使用 rowspan 标记)。 首先,删除包含命令按钮的单元格以外的其他所有单元格,以修改组成选定行(即用户单击的展开命令按钮所在的行)的单元格的数目。 如果假设展开命令列位于最左侧,这很容易实现。 所有单元格都删除后,可以创建一个横跨若干列(列数必须等于 DataGrid 控件的 Columns 集合中的项数)的全新单元格。

此时,您已拥有了使该行可展开的完全自定义单元格。 可以通过编程的方式在此自定义单元格中填入服务器控件的任意组合。 例如,可以插入这样一个表:最上面一行模拟已删除的单元格的结构(通常是关于父行的信息),最下面一行包含子 DataGrid。 图 2 中的控件是基于此方案创建的。

NestedGrid 类

前面已提到,NestedGrid 类从 System.Web.DataGrid 类继承,并添加了额外几个属性(见图 3)。 此控件还将在需要数据绑定时引发自定义的 UpdateView 事件。 要对分配给 DataSource 属性的对象类型加以严格的控制(并确保它是 DataSet),可以重写 DataSource 属性,如下面的代码所示:

public override object DataSource
{
get {return base.DataSource;}
set {
if (!(value is DataSet)) {
// throw an exception
}
base.DataSource = value;
}
}

当用户单击行按钮以展开记录(某个客户)查看其详细信息时,NestedGrid 控件实例化。 为此,嵌套的网格必须包含一个具有某些特定功能的按钮列。 首先,网格必须提供针对 ItemCommand 事件的处理程序,以便可以处理展开/折叠请求。 处理程序将 ExpandedItemIndex 属性设置为被单击的记录的基于零的索引,并更新网格视图。 那么,什么时候修改被单击的行的布局合适呢?

网格布局创建出来后,ItemDataBound 事件在事件链的底部激发。 ItemDataBound 激发后,数据绑定阶段基本完成,所有单元格都可以显示了。 此后您所看到的布局和数据将不会再发生任何变化。 就是因为这个原因,我决定在处理 ItemDataBound 事件之前实现所有必要的更改。

在深入探讨控件的实现之前,还有几点注意事项需要提出来。 首先,ExpandedItemIndex 属性是基于零的,但它表示的是所单击的行的绝对位置。 此属性与类似的网格属性(如 SelectedItemIndex 和 EditItemIndex)的唯一不同之处在于,它表示的不是基于页的值。 其次,NestedGrid 还在内部实现分页。 要使该控件在成员表的各页之间移动,除了处理 UpdateView 事件并传递绑定数据以外,不必做其他任何工作:

void UpdateView(object sender, EventArgs e) {
BindData();
}
void BindData() {
dataGrid.DataSource = (DataSet) Cache["MyData"];
dataGrid.DataBind();
}

NestedGrid 类具有针对 PageIndexChanged 事件的内置处理程序,如下所示:

void PageIndexChanged(object sender, DataGridPageChangedEventArgs e)
{
CurrentPageIndex = e.NewPageIndex;
SelectedIndex = -1;
EditItemIndex = -1;
ExpandedItemIndex = -1;

if (UpdateView != null)
UpdateView(this, EventArgs.Empty);
}

NestedGrid 控件的结构的关键要素是按钮列。 为简单起见,此版本的控件仅支持单个展开项。 通过将 ExpandedItemIndex 属性从整数更改为数组或集合,可以轻松地扩展此功能。

ExpandCommandColumn 类

可以使用字符串(如“+/-”或“Expand/Collapse”)或位图来呈现展开列。 您可能要对不同的应用程序使用不同的图片。 要实现此功能,最灵活的方法是使用几个像 ExpandText 和 CollapseText 这样的属性。 那么,应当在 NestedGrid 类上定义这些属性吗? 在类似的方案(就地编辑)中,ASP.NET 开发小组创建了一个自定义的 DataGrid 列,并在该列中放入了像 EditText、CancelText 和 UpdateText 这样的属性。 基于此,我创建了自己的 ExpandCommandColumn 类,并在其中放入了几个文本属性,以表示用于展开和折叠视图的 HTML 输出。 下面的代码片段显示了如何将该自定义列与网格集成。

<cc1:NestedDataGrid id="dataGrid" runat="server" ...>
<Columns>
<cc1:ExpandCommandColumn
CollapseText="<img src=http://www.163design.net/a/s/images/collapse.gif>"
ExpandText=

时间: 2024-12-31 04:25:56

用于显示分层数据的嵌套网格(from msdn)的相关文章

使用嵌套的Repeater控件显示分级数据

控件|数据|显示     简介       本文描述如何使用嵌套的Repeater 控件来显示分级数据 .当然了,你也可以将这一技术应用到其他的列表绑定控件上去,比如DataGrid包含DataGrid,DataList包含DataList等等的组合.       绑定到父表       1.添加一个新的Web Form 到应用程序项目中,名称为Nestedrepeater.ASPx.    2.从工具箱托动一个Repeater 控件到这个页面上, 设定其ID 属性为 parent .    3

Android 获取listview数据 然后赋值给popupwindow用于显示报空指针

问题描述 Android 获取listview数据 然后赋值给popupwindow用于显示报空指针 能得到数据但是给Textview赋值却报空指针! 下边贴代码. gv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) { // WindowManager.La

使用ASP.NET Atlas ListView控件显示列表数据

asp.net|控件|数据|显示 English Version: http://dflying.dflying.net/1/archive/113_display_listible_data_using_aspnet_atlas_listview_control.html 在这个系列中,我将介绍一些Atlas Sys.UI.Data中较高级的控件,包括: Sys.UI.Data.ListView:使用ASP.NET Atlas ListView控件显示列表数据 Sys.UI.Data.Item

如何使用 ASP.NET、ADO.NET 和 Visual C# .NET 查询和显示 Excel 数据

ado|asp.net|excel|visual|数据|显示 创建示例 Excel 工作表启动 Microsoft Excel,然后创建一个新的工作表. 将以下信息添加到新工作表中以创建一个简单的 Excel 数据库: A B 1 FirstName LastName 2 Scott Bishop 3 Katie Jordan 注意:虽然在本示例中数据是从单元格 A1 开始的,但是您可以将此数据添加到工作表中的任何相邻接的单元格. 突出显示此数据所在的行和列. 在插入菜单上,指向名称,然后单击定

WPF:使用Json.NET在TreeView中树形显示JSON数据

原文  WPF:使用Json.NET在TreeView中树形显示JSON数据 据 读者可以参考这个开源的可以树形显示XML和JSON的工具: Mgen Object 603:XML/JSON树形显示小工具 或者一个更大的开源工程(构建和分析HTTP并支持XML及JSON的树形显示): Mgen Bluckbadda   效果如下: (每一个项目中的左侧黑字是数据的值,右侧灰字是数据的类型.对于对象或数组,黑字会显示对象的属性个数或数组的成员个数) (上图中的JSON数据来自:http://www

在ASP.NET 2.0中操作数据之五十三:在Data Web控件显示二进制数据_自学过程

导言: 在前面的教程我们阐述了应用程序处理二进制数据的2种模式,以及使用FileUpload 控件从浏览器向服务器文件系统上传文件.当文件上传并存储在文件系统里时,应在相应的数据库记录里存储该文件的存储路径. 我们先来看如何为最终用户提供二进制数据.怎样展示二进制数据呢?这取决于其类型.比如图片,我们将其显示为image:如果是PDFs,Microsoft Word文档.ZIP文件或其它类型的数据,或许提供一个"Download"链接比较妥当. 在本节,我们看如何在GridView和D

html页面下拉列表中动态添加后台数据(格式化数据,显示出数据的层次感)

html页面下拉列表中动态添加后台数据(格式化数据,显示出数据的层次感) 效果图:     运行原理和技术: 当页面加载完毕,利用jquery向后台发送ajax请求,去后台拼接<select></select>中的option字符串.让后将字符串响应回来,动态添加到<select>中.其中的字符串中包含了后台的数据. 页面js代码:   1 <script type="text/javascript"> 2 //加载部门 3 functi

ASP实现表格形式显示数据库数据

数据|数据库|显示 前面的代码省略了,就是连接数据库的代码,具体以表格形式显示数据库数据的代码如下: <table border=1><tr><%for i=0 to rs.fields.count-1response.write("<td>"&rs(i).name&"</td>")next%></tr><%rs.movefirstwhile not rs.Eofrespo

ASP.NET MVC Framework体验(2):显示列表数据

概述 ASP.NET WebForm下,显示列表数据,经常会使用服务器控件GridView. DataList等.在ASP.NET MVC Framework中,我们有两种方式进行显示数据,一是使用行内 代码,即通过循环视图数据使用<%=%>标记进行呈现:二是使用服务器控件,同样可 以把视图数据绑定在服务器控件,如ASP.NET 3.5中的新控件ListView. 准备数据访 问 这里我们显示一个Post的列表DataContext和实体定义如下: [Database(Name="B