使用 AJAX 的分层 GridView 控件






2.69/5 (14投票s)
解释如何在 ASP.NET 中使用 AJAX 创建分层 GridView 控件
引言

本文讲解了如何创建一个分层 GridView 控件。我在一个项目中实现了这个 GridView,大约两年前。当时我就想发布它,但由于时间不够而未能如愿。现在,在紧张的时间安排下,我终于发布了它。您可以使用这个 GridView 来以父子模型显示数据。在这个例子中,我只使用了一个子 GridView。使用这段代码,您可以通过在子 GridView 下创建更多的子 GridView 来将子 GridView 转换为父 GridView。
背景
该项目使用了两个 GridView
和两个 ObjectDataSource
。GridView
的 ID 分别是 grdOrders
和 grdOrderDetails
。SQL Express 被用作后端服务器,NorthWind 是该模块的数据库。在本例中,grdOrders
被称为父 GridView,grdOrderDetails
被称为子 GridView,它位于 grdOrders
内部。默认情况下,子 GridView 的 Visible
属性为 false
。父 GridView 将显示订单。当用户点击父 GridView 的某一行时,子 GridView 将可见并显示订单详情数据。
Using the Code
这是用于从业务逻辑层提取数据的 ObjectDataSource
声明:
<asp:ObjectDataSource ID="objDataSourceID"
runat="server"
SelectMethod="GetOrders"
EnablePaging="true"
TypeName="clsGeneralFunctions"
StartRowIndexParameterName="StartRowIndex"
MaximumRowsParameterName="MaximumRows"
SelectCountMethod="GetOrdersCount">
</asp:ObjectDataSource>
上面的 ObjectDataSource
用于从业务逻辑层为父 DataGrid
提取数据。StartRowIndexParameterName
和 MaximumRowsParameterName
属性用于仅提取当前页面需要显示的数据记录。SelectCountMethod
属性用于拉取实际查询将返回的总记录数,该数量用于根据 PageSize
属性在 GridView 上显示总页数。当用户在 GridView 中选择某个页码时,ObjectDataSource
将执行分配给 SelectMethod
属性的 GetOrders
方法。如果 EnablePaging
属性设置为 False
,那么 StartRowIndexParameterName
和 MaximumRowsParameterName
属性就没有意义了,也就是说,我们无法仅拉取当前页面需要显示的数据记录。
<asp:ObjectDataSource ID="objOrderDetails"
runat="server"
SelectMethod="GetOrdersDetailsList"
EnablePaging="true"
TypeName="clsGeneralFunctions"
SelectCountMethod="GetOrdersDetailsCount">
<SelectParameters>
<asp:Parameter Direction="Input"
Name="StartRowIndex" type="Int32" />
<asp:Parameter Direction="Input"
Name="MaximumRows" type="Int32" />
<asp:Parameter Direction="Input"
Name="OrderId"
DefaultValue="0" type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
上面的 ObjectDataSource
用于从业务逻辑层为子 DataGrid
提取数据,数据基于来自父 GridView 的 Order ID。当用户点击父 GridView 的某个订单时,子 GridView 将显示所选订单的订单详情。上面的 ObjectDataSource
有一个额外的输入参数,名为 OrderId
,用于将 Order ID 传递给分配给 SelectCountMethod
和 SelectMethod
属性的方法。
protected void grdOrders_RowDataBound(object sender, GridViewRowEventArgs e)
{{
ImageButton imgBtn;
if (e.Row.RowType == DataControlRowType.DataRow)
{
imgBtn = (ImageButton)(e.Row.FindControl("ImgBtn"));
imgBtn.CommandArgument = e.Row.RowIndex.ToString();
if (e.Row.Cells[0].Text == Session["OrderId"])
{
PlaceHolder objPH;
objPH = (PlaceHolder)(e.Row.FindControl("objPHOrderDetails"));
if (objPH != null)
objPH.Visible = true;
if (imgBtn.ImageUrl == "Include/images/gridplus.gif")
imgBtn.ImageUrl = @"Include/images/gridminus.gif";
else
imgBtn.ImageUrl = @"Include/images/gridplus.gif";
}
}
}
当 GridView
中的行被创建时,会触发上面的 RowDataBound
事件。该事件用于将 GridView
的行号设置为 ImageButton
的 CommandArgument
属性。当用户点击父 GridView 上的 ImageButton
时,该属性将在父 GridView 的 RowCommand
事件中使用。
protected void grdOrders_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Expand")
{
ImageButton imgbtn;
GridView gv = (GridView)(sender);
Int32 rowIndex = Convert.ToInt32(e.CommandArgument.ToString());
PlaceHolder objPH =
(PlaceHolder)(gv.Rows[rowIndex].FindControl("objPHOrderDetails"));
ObjectDataSource objDS =
(ObjectDataSource)(gv.Rows[rowIndex].FindControl("objOrderDetails"));
GridView objChildGrid =
(GridView)(gv.Rows[rowIndex].FindControl("grdOrderDetails"));
imgbtn = (ImageButton)(gv.Rows[rowIndex].FindControl("ImgBtn"));
objDS.SelectParameters["OrderId"].DefaultValue =
gv.DataKeys[rowIndex][0].ToString();
Session["OrderId"] = gv.DataKeys[rowIndex][0].ToString();
if (imgbtn.ImageUrl == "Include/images/gridplus.gif")
{
imgbtn.ImageUrl = @"Include/images/gridminus.gif";
if (objChildGrid != null)
{
if (objPH != null)
objPH.Visible = true;
objChildGrid.Visible = true;
}
}
else
{
if (objChildGrid != null)
{
imgbtn.ImageUrl = @"Include/images/gridplus.gif";
if (objPH != null)
objPH.Visible = false;
objChildGrid.Visible = false;
}
}
}
}
if
条件 (e.CommandName == "Expand"
) 用于验证用户是否点击了 ImageButton
。值 "Expand
" 已被设置为 ImageButton
的 CommandName
属性。当用户点击 ImageButton
时,我们将创建父 GridView 控件中所有控件的对象,将选定的行(即 Order ID)传递给子数据源,该子数据源将拉取所选订单的所有订单详情记录。一旦数据被填充到子 GridView 中,我们就应该将加号(+)符号的图像按钮更改为减号(-)符号,并将子 GridView 和 PlaceHolder
的 Visible
属性设置为 true
。下次用户点击同一行时,减号符号应更改为加号符号,并将子 GridView 和 PlaceHolder
的 Visible
属性设置为 false
,这由 else
语句实现。
关注点
由于我们对 ASP.NET 比较陌生,因此在这个项目中学习了许多新控件。