GridView 中的可展开面板






4.82/5 (45投票s)
在 GridView 中展开详细信息面板的另一种方法。
引言
几周前,一位客户问我:“我们需要一个简单的列表,并且我们需要点击查看列表中的详细信息 - 不是弹出窗口 - 不是另一个页面 - 不是重新加载整个页面”。我开始搜索、阅读、测试。 我找到了一些有趣的文章和示例,但不是我的客户真正想要的。 然后我想:我可以合并一些解决方案,也许可以满足客户的需求。 AJAX DynamicPopulate
扩展器提供了该机制。 让我们打开源代码并学习。 一些有趣的文章提出了一些好主意。 让我们阅读和学习。
我想在这篇文章中分享这项工作的成果。
您可以在这里看到示例项目运行(仅使用模拟数据)。
背景
当 AJAX DynamicPopulate
扩展器启动时,它会调用某个页面或 Web 服务上的一个方法,接收一些结果,并填充一个控件。
我们可以使用 JavaScript 函数来启动扩展器,并且可以捕获结果并填充另一个控件。当用户单击网格第一列中的按钮时,JavaScript 函数会被激活。
Using the Code
主页面有一个包含三列的 GridView
:一个模拟按钮的图像,用于显示和隐藏详细信息,商店名称和销售额总和。
场景是Adventure Works Cycles,这是一家虚构的大型跨国制造公司。 网格显示了顶级商店。 当用户单击按钮时,会展开一个面板并显示前五个模型。
图像/按钮的 onclick
事件调用一个 JavaScript 函数 (ExpandModels
),其中包含以下参数:客户 ID、网格视图的行、目标面板和单击的按钮。
// Default.aspx.cs :
protected void gridStores_RowDataBound(object sender, GridViewRowEventArgs e) {
...
Image btn = gridViewRow.FindControl("imgModel") as Image;
btn.Attributes["onClick"] = String.Format(CultureInfo.InvariantCulture,
"ExpandModels('{0}', '{1}', '{2}', '{3}');",
contextKey, // customerID + some data
newRow.ClientID, // Row of gridview, below the row that was clicked
internalPanel.ClientID, // Destination panel, wich will receive the details
btn.ClientID); // The clicked button
...
}
JavaScript 函数 ExpandModels
执行一些准备工作,并启动 DynamicPopulate
扩展器的 'behavior' dpBehaviorMod
的 populate
方法,传递客户 ID。 'behavior' 将向 WebMethod ExpandModelsService
发送回调,该 WebMethod 将构建一个 HTML 表格并将其发送回浏览器。
// ExpandPanel.js :
var expPainelId = ''; // ID of the internal panel where the details will be inserted
var expPainelAuxId = 'painelAux'; // Receives the results from the WebMethod
function ExpandModels(customerId, trId, painelId, buttonId) {
...
var tr = $get(trId).style;
tr.display='block'; // Shows the panel ('table-row' for Firefox)
lastBehavior = $find('dpBehaviorMod');
expPainelId = painelId;
lastBehavior.add_populated(ShowTopModels); // Sets the handle
lastBehavior.populate(customerId); // Calls the WebMethod
}
<!-- Default.aspx -->
<cc1:DynamicPopulateExtender ID="dinPopMod"
runat="server"
BehaviorID="dpBehaviorMod"
CacheDynamicResults="false"
ClearContentsDuringUpdate="true"
EnableViewState="False"
ServiceMethod="ExpandModelsService"
TargetControlID="painelAux">
</cc1:DynamicPopulateExtender>
<asp:Panel ID="painelAux"
runat="server"
EnableViewState="false"
Style="background-image:url('img/loading.gif');
background-repeat: no-repeat; display: none">
</asp:Panel>
当扩展器返回时,它会填充辅助面板 'painelAux
'(由属性 TargetControlID
指示),然后另一个 JavaScript 函数 (ShowTopModels
) 将结果复制到目标面板。 面板 ID 由函数 ExpandModels
保存在变量 expPainelId
中。
// ExpandPanel.js :
function ShowTopModels(s, e) {
// The internal panel where the details will be inserted
var p1 = $get(expPainelId);
// The aux panel filled by the DynamicPopulateExtender
var p2 = $get(expPainelAuxId);
...
// Details HTML table
p1.innerHTML = p2.innerHTML;
...
}
在 web 方法内部,程序构建一个包含详细信息的简单 HTML 表格。
[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod]
public static string ExpandModelsService(string contextKey) {
...
StringBuilder sb = new StringBuilder("<table class = 'tab-mod'> \n"
+ "<tr> \n"
+ "<th>Model</th> \n"
+ "<th>Qty</th> \n"
+ "<th>Total price</th> \n"
+ "<th>Last sale</th> \n"
+ "</tr> \n",
topModels.Count * 180);
...
sb.Append("<tr> \n");
sb.AppendFormat(CultureInfo.CurrentCulture,
"<td>{0}</td> ",
modelRow.Name);
...
sb.Append("</table> \n");
return sb.ToString();
}
以上代码片段摘自示例项目并经过简化。 完整的源代码可供下载。
关注点
当页面发送到浏览器时,只会发送主列表(商店)。 当用户单击每一行上的按钮时,模型将动态发送。 我们可以使用另一种方法在第一次加载所有数据,然后在 onclick
事件中隐藏/显示。 这种方法可能会导致加载整个页面花费很长时间。
'loading.gif' 文件由面板 'painelAux
' 预加载,以加快用户单击按钮时的显示速度。
我将 WebMethod ExpandModelsService
包含在 'Default.aspx' 中。 如果项目包含很多 WebMethod,我们可以创建一个或多个 'asmx' 文件来帮助我们组织项目。
结论
如果这篇文章能以任何形式帮助到您,我将很高兴。
当然,您可以在示例项目中找到许多错误、bug 和不太好的代码。 我提前感谢您的提示、建议和更正。
参考文献
已经有很多关于这个主题的好文章
- 在 DataGrid 中显示钻取行 by Yes'B
- 使用 AJAX 弹出窗口在 GridView 中显示扩展详细信息(第 1 部分) by Brian Smith
- JavaScript 可扩展/可折叠面板控件 by SAMir Nigam
- 可折叠 DataGrid 和 GridView 控件 by Mukesh Singhi
- 在 GridView 中显示可折叠数据 by Dipak Riswadkar
- 分层数据和 ASP.NET DataGrid by Dion Le Roux