ASP.NET GridView 控件扩展

Web开发中,有时需要扩展Web控件的功能和行为。ASP.NET 控件提供了多种扩展点,包括可定制属性、样式和CSS类、模板化以及重写。虽然前三个选项可以在运行时配置,但第四个选项需要一些编码工作。当想要改变控件的行为或布局时,通常需要创建一个Web控件的子类,在其中实现重写的方法。

本文将展示一个示例,说明如何扩展标准的ASP.NETGridView 控件,使其能够显示滚动条(即带有固定头部的可滚动表格),而不是使用标准的分页,从而允许一次性显示所有列表项。此解决方案已在Internet Explorer、Firefox和Chrome浏览器中进行了测试。

Web标准规定在浏览大型列表时使用分页功能。其理念是大型列表需要较长时间下载,因此使用分页时,用户只需要下载包含少量行的单页。然而,标准的ASP.NETGridView 默认支持分页,但并没有显著优化加载时间,因为绑定到GridView的列表默认存储在ViewState中,因此仍然生成了一个较大的页面,导致下载时间较长。

因此,可以选择忽略分页并一次性显示完整列表。这样做的好处是,用户在选择GridView的不同页面时,页面不需要重新加载。显然,列表可能会变得太大,无法适应单个Web页面,因此使用滚动条是一个足够的解决方案。这在桌面应用程序中相当常见。然而,发现向GridView添加滚动条并不完全简单:目标是仅使列表项可滚动,同时保留GridView头部固定。

解决方案

解决方案的方法并不新颖,例如,可以参考这里的例子。基本上,标题行显示在一个标题DIV中的表格中,而主体行显示在一个单独的可滚动主体DIV元素中。这种方法需要解决以下问题:

从GridView中提取标题行并在单独的DIV和TABLE中渲染。这需要一些调整才能使其工作。它需要覆盖GridView控件的默认RenderChildren方法。RenderChildren方法负责生成输出,该输出写入响应对象。而不是生成默认的GridView HTML元素,重新排列并插入了一些自己的HTML元素。

创建一个新的标题DIV HTML元素。为其分配一个特殊的CSS类,以便可以从JQuery中访问。

System.Web.UI.HtmlControls.HtmlGenericControl divhead = new System.Web.UI.HtmlControls.HtmlGenericControl("DIV"); divhead.Attributes["class"] = "GridViewHeaderContainer"; divhead.Style.Add("overflow", "hidden"); if (this.Width != Unit.Empty) divhead.Style.Add("width", this.Width.ToString());

创建一个新的Table对象并将其插入到标题DIV中。确保应用了正确的样式。

Table tablehead = new Table(); tablehead.ApplyStyle(this.HeaderStyle); tablehead.Style.Add("width", "100%"); tablehead.ID = ctrl.UniqueID + "$Header"; divhead.Controls.Add(tablehead);

选择GridView中的标题行并将其插入到新创建的表格中(注意,这将从原始表格中移除该行!)。

WebControl ctrl = (WebControl)this.Controls[0]; Control ctrlrow = ctrl.Controls[0]; tablehead.Controls.Add(ctrlrow);

渲染标题DIV(这将自动渲染其子元素)。

divhead.RenderControl(writer);

创建主体DIV。

System.Web.UI.HtmlControls.HtmlGenericControl divbody = new System.Web.UI.HtmlControls.HtmlGenericControl("DIV"); divbody.Attributes["class"] = "GridViewBodyContainer"; if (this.Width != Unit.Empty) divbody.Style.Add("width", this.Width.ToString()); if (this.Height != Unit.Empty) divbody.Style.Add("height", this.Height.ToString()); divbody.Style.Add("margin", "0px"); divbody.Style.Add("overflow", "hidden"); divbody.Style.Add("overflow-y", "auto");

将标题行重新插入到原始表格中的位置0(顶部)。

ctrl.Controls.AddAt(0, ctrlrow);

将GridView表格插入到主体DIV中并渲染主体DIV。

divbody.Controls.AddAt(0, ctrl); divbody.RenderControl(writer);

将表格重新插入到GridView中。这是必要的步骤,因为它将GridView恢复到原始状态。

this.Controls.AddAt(0, ctrl);

渲染GridView中的任何其他控件(例如,页脚)。

for (int i = 1; i < this.Controls.Count; i++) { ctrl = (WebControl)this.Controls[i]; ctrl.RenderControl(writer); }

对齐标题行的列与主体表格中的列。为了确保两个表格的列对齐,需要使用一些JavaScript/JQuery。脚本包含一个名为UpdateGrid()的函数,该函数在GridView完全渲染后调用。此时,列宽已知,并在运行时重新对齐。它将根据其CSS类查找DIV,并遍历所有行和列以确定宽度。然后,它将为每个表格单元格显式设置宽度。

完成后,它将使主体中的第一行(即原始标题行)不可见。因为这是在渲染后完成的,有时这可能导致在一瞬间显示两个标题头。这是这种方法的唯一缺点。

在UpdatePanel中使用Grid

为了支持从UpdatePanel内更新Grid,需要一些额外的JavaScript,以确保Grid在每次(部分)回发到服务器后正确刷新和重新对齐。每当UpdatePanel更新其内容时,它必须调用UpdateGrid() JavaScript函数。为此,必须在网页中ScriptManager声明之后声明以下处理程序:

<asp:ScriptManager ID="ScriptManager1" runat="server" /> <script type="text/javascript"> Sys.Application.add_load(function() { UpdateGrid(); }); </script>

这个小技巧将使网格与UpdatePanel保持同步。

使用代码

提供的解决方案包含2个文件:ScrollableGridView.cs和ScrollableGridView.js。可以将这些文件添加到自己的ASP.NET解决方案中,或者直接从ControlExtensions组件中使用ScrollableGridView。需要从Web项目中添加对组件的引用。

将以下行添加到网页中:

<%@ Register TagPrefix="ce" Namespace="Grids" Assembly="ControlExtensions" %> <script type="text/javascript" src="Scripts/jquery-1.4.1.min.js"></script> <script type="text/javascript" src="Scripts/ScrollableGridView.js"></script>

...

在页面的所需位置插入可滚动的GridView控件,确保设置控件的高度属性以确保显示滚动条

<ce:ScrollableGridView id="ScrollableGridView1" runat="server" height="360px" width="100%"> <HeaderStyle BackColor="Orange" /> </ce:ScrollableGridView>

这足以支持GridView中的滚动。在本文包含的示例应用程序中,生成了一些随机行以填充列表。这在页面的代码后台中完成,仅用于测试目的。

此外,还添加了一个示例网页,展示了如何将网格与UpdatePanel控件结合使用。

要点

很高兴地发现,通过覆盖RenderChildren方法,GridView可以以非常不同的方式进行渲染。这允许轻松重用和扩展现有的ASP.NET控件。

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