ASP.NET AJAX 控件的合理使用

ASP.NET开发中,AJAX控件提供了一种便捷的方式来实现页面的异步更新,从而提升用户体验。然而,如果不正确地使用这些控件,可能会导致一些意想不到的问题。例如,如果每行都有一个按钮,点击该按钮需要异步更新页面上被UpdatePanel包围的区域,那么就需要谨慎处理。

一种解决方案是将整个GridView放入一个UpdatePanel中。由于UpdatePanel有一个默认值为"true"的属性"ChildrenAsTriggers",这意味着任何从GridView发出的回发都会导致异步回发。但是,这是否意味着每次点击特定行中的按钮时,整个GridView都会被发送回服务器,然后在回传时GridView会被刷新?是的,这是真的,这就是为什么在上面提到,应该正确使用AJAX服务器控件,即:

使用但不要过度使用!

解决方案

情况是这样的。有一个UpdatePanel,里面包含一个Label,显示当前的DateTime值。在这个UpdatePanel下方,有一个GridView,列出了AdventureWorks数据库中Vendors数据表的数据。对于每一行,都有一个Select按钮,点击后应该导致异步回发,从而更新上方UpdatePanel中的Label。以下是ASPX标记:

<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager> <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional"> <ContentTemplate> <asp:Label ID="lblName" runat="server" /> </ContentTemplate> </asp:UpdatePanel> <asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" AutoGenerateColumns="False" onrowdatabound="GridView1_RowDataBound"> <Columns> <asp:BoundField DataField="ActiveFlag" HeaderText="ActiveFlag" SortExpression="ActiveFlag" /> <asp:BoundField DataField="VendorID" HeaderText="VendorID" InsertVisible="False" ReadOnly="True" SortExpression="VendorID" /> <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" /> <asp:TemplateField HeaderText="Command"> <ItemTemplate> <asp:UpdatePanel ID="gridUpdatePanel" runat="server"> <ContentTemplate> <asp:LinkButton ID="lbtnSelect" Text="Select" runat="server" CommandName="Select" onclick="lbtnSelect_Click" /> </ContentTemplate> </asp:UpdatePanel> </ItemTemplate> </asp:TemplateField> </Columns> </asp:GridView> <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>" SelectCommand="SELECT TOP 5 [ActiveFlag], [VendorID], [Name] FROM [Purchasing].[Vendor]"/>

聪明的做法是只将包含Select按钮的列放入UpdatePanel中,如代码中加粗的部分所示。然后,当这个LinkButton被点击时,将进行异步回发并更新主UpdatePanel中Label的内容。此外,需要将第一个UpdatePanel的UpdateMode设置为"Conditional",这样页面上的每个异步回发就不会导致它刷新其内容。

剩下的就是在C#中编写LinkButton的事件处理程序代码:

protected void lbtnSelect_Click(object sender, EventArgs e) { this.lblName.Text = DateTime.Now.ToString(); this.UpdatePanel1.Update(); }

如所见,执行了对UpdatePanel的Update()方法的调用。这将导致UpdatePanel1在客户端刷新其内容。如之前所见,UpdatePanel没有定义任何触发器,并且其UpdateMode设置为Conditional,因此刷新其内容的唯一方法是手动调用其Update()方法。

在FireFox中测试此代码并打开Firebug时,可以看到服务器返回的响应如下:

62|updatePanel|UpdatePanel1| <span id="lblName">2/18/2008 6:51:14 PM</span> |165|updatePanel|GridView1_ctl02_gridUpdatePanel| <a id="GridView1_ctl02_lbtnSelect" href="javascript:__doPostBack('GridView1$ctl02$lbtnSelect', '')">Select</a> |165|updatePanel|GridView1_ctl03_gridUpdatePanel| <a id="GridView1_ctl03_lbtnSelect" href="javascript:__doPostBack('GridView1$ctl03$lbtnSelect', '')">Select</a> |165|updatePanel|GridView1_ctl04_gridUpdatePanel| <a id="GridView1_ctl04_lbtnSelect" href="javascript:__doPostBack('GridView1$ctl04$lbtnSelect', '')">Select</a> |165|updatePanel|GridView1_ctl05_gridUpdatePanel| <a id="GridView1_ctl05_lbtnSelect" href="javascript:__doPostBack('GridView1$ctl05$lbtnSelect', '')">Select</a> |165|updatePanel|GridView1_ctl06_gridUpdatePanel| <a id="GridView1_ctl06_lbtnSelect" href="javascript:__doPostBack('GridView1$ctl06$lbtnSelect', '')">Select</a> |0|hiddenField|__EVENTTARGET||0|hiddenField|__EVENTARGUMENT||704|hiddenField |__VIEWSTATE/ ViewState cut down

哦,出了什么问题?可以看到,整个GridView都被刷新了!这违背了上面提到的目的!!嗯,永远不会从错误中学到东西!让思考一下,每一行现在都包含一个UpdatePanel,每个UpdatePanel都有UpdateMode="Always"和ChildrenAsTriggers="True" - 默认值。这清楚地解释了为什么点击SelectLinkButton时整个GridView被刷新了。

如何解决这个问题?

所需要做的就是在GridView内部的UpdatePanel中添加以下内容:

UpdateMode="Conditional" ChildrenAsTriggers="false"

这告诉GridView内部的UpdatePanel,在每次异步回发时不要刷新,也不要通过UpdatePanel内容中的任何事件刷新。换句话说,永远不要刷新这个UpdatePanel。只要不关心GridView行内更新的任何内容,这就是真的。只要想要执行的是刷新GridView外部的其他内容,这就是一个很好的解决方案。

现在,再次运行相同的代码并使用FireFox和Firebug进行测试,可以看到响应已经减少到只有ViewState和要更新的包含Label的上方UpdatePanel的内容:

62|updatePanel|UpdatePanel1| <span id="lblName">2/18/2008 7:01:01 PM</span>    |0|hiddenField|__EVENTTARGET||0|hiddenField|__EVENTARGUMENT||704|hiddenField|__VIEWSTATE| ViewState cut down

可以看到通过添加这两个属性获得了多少好处?现在问题已经解决了,GridView包含一个按钮来更新外部的UpdatePanel,并且性能得到了很好的提升!想象一下,这对于在GridView中显示大量数据会有多大的帮助?

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485