ASP.NET 中的嵌套 GridView 控件:最佳实践
ASP.NET GridView 控件在以数据为中心的 Web 应用程序中托管另一个 GridView
通用解决方案
在 ASP.NET 中嵌套GridView
控件几乎在 Microsoft 的“规范”演练 [1] 中有所描述。通常,它需要创建两个 GridView
控件:第一个作为容器或主 GridView1
,具有其自己的 DataSource1
(SqlDataSource
、AccessDataSource
等),第二个“嵌套”GridView2
,其底层 DataSource2
位于主 GridView1
的 TemplateField
中。代码片段 [1] 在 GridView1 RowDataBound
事件过程 (GridView1_RowDataBound
) 内部,用于将“外键”值从 GridView1
传递到 DataSource2
。在 [1] 中提供的特定示例中,存储在 GridView1
第一单元格中的“外键” (e.Row.Cells[0].Text
) 被传递给 SqlDataSource2 的仅一个 SelectParameter
(SelectParameters[0]
) 的 DefaultValue
属性清单 1. MSDN 上带有硬编码 Cells 索引的原始解决方案
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e){
if (e.Row.RowType == DataControlRowType.DataRow)
{
SqlDataSource s = (SqlDataSource)e.Row.FindControl("SqlDataSource2");
s.SelectParameters[0].DefaultValue = e.Row.Cells[0].Text;
}
}
这应该适用于所有实际版本的 ASP.NET (2.0/3.5/4.0)。但是,此解决方案的潜在缺点在于外键值(例如,ID)可能会从 GridView1
控件的可见字段集中省略。此外,即使此外键字段存在于 GridView1
中,也可能存在硬编码单元格索引 0
的不便;通常,它可能不是字段集中的第一个,并且它的索引也可能在数据表编辑操作期间或由于动态重新排列表列顺序而动态更改。更好的解决方案
以下清单 2 中显示的更好解决方案通过在GridView1
控件中使用命名的 DataKeys
作为第二个 DataSource
的“外键”,有效地解决了上述所有潜在问题。在此特定示例中,DataKey
“Composer
”被添加到 GridView1 控件的 DataKeys
中(需要 DataKeyNames="Composer"
行),以便传递到第二个 DataSource
(名为 “dsMusic
”) 的相应 select 参数 s.SelectParameters[0].DefaultValue
。清单 2. 使用 DataKeys 的改进版本
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) {
if (e.Row.RowType == DataControlRowType.DataRow)
{
// find DataSource used for nested GridView (could be SqlDataSource)
AccessDataSource s = (AccessDataSource)e.Row.FindControl("dsMusic");
// assign parameter’s default value from the DataKeys in GridView1
s.SelectParameters[0].DefaultValue = Convert.ToString(((GridView)sender).DataKeys[e.Row.RowIndex].Values["Composer"]);
}
}
注意:清单 2 演示了 ASP.NET AccessDataSource
的使用,但概念/用法与 SqlDataSource
几乎相同。
示例演示
在线音乐库,带有附加的 YouTube 播放器 [2-4],使用上述嵌套GridView
技术实现:单击下面的图片以查看工作演示: 
性能提升
通过为嵌套DataSource
启用缓存并使用 FilterParameters
而不是 SelectParameters
,可以实现显著的性能改进。为此- 设置嵌套的
DataSource
属性;FilterExpression="Composer ='{0}'" EnableCaching="True"
- 通过替换将
SelectParameters
分配给以下行的行来修改清单 2 中的事件过程// assign filter parameter default value from the datakey s.FilterParameters[0].DefaultValue = Convert.ToString(((GridView)sender).DataKeys[e.Row.RowIndex].Values["Composer"]);