在ASP.NET 2.0中操作数据之十五:在GridView的页脚中显示统计信息

   2016-05-11 0
核心提示:本文主要介绍在GridView中显示页脚的实现方法,通过设置ShowFooter设置为True,再配合事件和底层的方法从而实现在GridView的页脚区域显示相关的统计信息。

导言

  除了需要了解产品的单价、库存量和订货量,并按等级排序之外,用户可能还对统计信息感兴趣,比如说平均价格、库存总量等等。这些统计信息常常显示在报表最下面的一个统计行中。GridView控件可以含有一个页脚行,我们可以通过编程将统计数据插入到它的单元格里面去。这个任务给了我们以下3个挑战:

1.配置GridView以显示它的页脚行

2.确定统计数据。即我们应该如何计算平均价格还有库存总量?

3.将统计信息插入到页脚行的相应的单元格中

  在本节教程中,我们将会看到如何去征服这些挑战。另外呢,我们将创建一个页面,它含有一个列出所有“类别”的下拉框,选择一个“类别”就可以在GridView中显示这个类别的产品。GridView中包含一个页脚行,用于显示此类产品的平均价格、库存总量和订货总量。

在ASP.NET 2.0中操作数据之十五:在GridView的页脚中显示统计信息

图一:统计信息显示在GridView的页脚行中

  由于含有“类别”到“产品”的主/从界面,所有本节是建立在前面的“使用DropDownList进行主/从过滤”节中所讨论的那些概念的基础上的。如果你还没有看过那一节的话,在继续本节的学习之前,还是去看看比较好。

第一节:添加“类别”下拉框和“产品”GridView

  往GridView中添加页脚行之前,让我们先来简单的建立一个主/从报表。一旦我们完成了这第一步的工作,我们就可以来看看如何加入统计数据了。

  首先打开CustomFormatting文件夹中的SummaryDataInFooter.aspx页面。添加一个DropDownList控件,并将其ID设置为Categories。然后,在这个DropDownList的智能标签上点击“选择数据源(Choose Data Source)”,添加一个新的调用CategoriesBLL类的GetCategories ()方法的ObjectDataSource控件,将这个ObjectDataSource命名为CategoriesDataSource。

在ASP.NET 2.0中操作数据之十五:在GridView的页脚中显示统计信息

图二:添加一个新的名为CategoriesDataSource的ObjectDataSource控件

在ASP.NET 2.0中操作数据之十五:在GridView的页脚中显示统计信息

图三:使这个ObjectDataSource控件调用CategoriesBLL类的GetCategories ()方法

  再配置了了ObjectDataSource之后,向导会将我们返回到DropDownList的数据源配置向导那里,在这儿我们可以指定哪个字段需要显示以及哪个字段应该作为DropDownList的ListItem的值。我们将CategoryName字段拿来显示,而把CategoryID拿来作为值。

在ASP.NET 2.0中操作数据之十五:在GridView的页脚中显示统计信息

图四:分别使用CategoryName和CategoryID来作为ListItem的文本和值

  现在,我们便在系统中有了一个能列出类别的DropDownList了。现在我们需要添加一个根据所选的类别来列出产品的GridView。不过,在此之前,让我们先花点时间到DropDownList的智能标签中勾上“启用自动回发(Enable AutoPostBack)”复选框。我们在前面的“使用DropDownList进行主/从过滤 lidong6”节中讨论过,在将DropDownList的AutoPostBack属性设置为true之后,只要DropDownList的值发生了变化,页面就会回发。这样就可以刷新GridView以显示新选择的类别的产品了。如果AutoPostBack属性设置为false(默认值),改变类别将不会导致回发,因此也就不能刷新产品列表了。

在ASP.NET 2.0中操作数据之十五:在GridView的页脚中显示统计信息

图五:在DropDownList的智能标签中勾上“启用自动回发”复选框

  添加一个GridView控件到页面上以便可以根据选定的类别来显示产品。将这个GridView的ID设置为ProductsInCategory,并将其绑定到一个新的名为ProductsInCategoryDataSource的ObjectDataSource上。

在ASP.NET 2.0中操作数据之十五:在GridView的页脚中显示统计信息

图六:添加一个新的名为ProductsInCategoryDataSource的ObjectDataSource

配置这个ObjectDataSource,以使其调用ProductsBLL类的GetProductsByCategoryID(categoryID)方法。

在ASP.NET 2.0中操作数据之十五:在GridView的页脚中显示统计信息

图七:使这个ObjectDataSource调用GetProductsByCategoryID(categoryID)方法

  由于GetProductsByCategoryID(categoryID)方法需要一个参数,所以在向导的最后一步里,我们可以指定参数值的数据源。为了根据显示所选的类别来显示产品,这个参数应该从Categories下拉框中获取。

在ASP.NET 2.0中操作数据之十五:在GridView的页脚中显示统计信息

图八:从Catefories下拉框中获取categoryID参数

  完成了向导之后,这个GridView将会包含一些对应于产品的每一个属性的BoundField。让我们来清理一下这些BoundField,剩下要显示的ProductName、UnitPrice、UnitsInStock以及UnitsOnOrder就可以了。然后你可以随便的给剩下的这些BoundField添加一些字段级的设置(比如说将UnitPrice格式化为货币形式)。做了这些更改之后,这个GridView的声明标记应该是这个样子:

<asp:GridView ID="ProductsInCategory" runat="server"
  AutoGenerateColumns="False" DataKeyNames="ProductID"
  DataSourceID="ProductsInCategoryDataSource" EnableViewState="False">
  <Columns>
    <asp:BoundField DataField="ProductName" HeaderText="Product"
     SortExpression="ProductName" />
    <asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"
      HeaderText="Price"
      HtmlEncode="False" SortExpression="UnitPrice">
      <ItemStyle HorizontalAlign="Right" />
    </asp:BoundField>
    <asp:BoundField DataField="UnitsInStock"
     HeaderText="Units In Stock" SortExpression="UnitsInStock">
      <ItemStyle HorizontalAlign="Right" />
    </asp:BoundField>
    <asp:BoundField DataField="UnitsOnOrder"
      HeaderText="Units On Order" SortExpression="UnitsOnOrder">
      <ItemStyle HorizontalAlign="Right" />
    </asp:BoundField>
  </Columns>
</asp:GridView>

现在,我们就拥有了一个可以根据所选类别来显示相关的产品的名称、单价、库存量以及订货量的功能齐全的主/从报表了。

在ASP.NET 2.0中操作数据之十五:在GridView的页脚中显示统计信息

图九:现在的效果(译者注:估计原文这里弄错了,写得跟图八的一样。这里的原文是“Figure 9: Get the categoryID Parameter Value from the Selected Categories DropDownList”,图八的原文是“Figure 8: Get the categoryID Parameter Value from the Selected Categories DropDownList”)

第二步:在GridView中显示页脚

  GridView控件可以显示页眉和页脚行。这些行的显示与否分别取决于ShowHeader和ShowFooter属性,默认情况下,ShowHeader的值为true,而ShowFooter的值为false。要显示页脚行的话,我们只需简单的将ShowFooter属性设置为true就可以了。

在ASP.NET 2.0中操作数据之十五:在GridView的页脚中显示统计信息

图十:将GridView的ShowFooter属性设置为true

  GridView中所定义的每一个字段都在页脚行中有一个对应的单元格,不过这些单元格默认是空的。花点时间到浏览器中看看我们的成果。由于我们将GridView的ShowFooter属性设置为true了,所以GridView现在包含了一个空的页脚行。

在ASP.NET 2.0中操作数据之十五:在GridView的页脚中显示统计信息

图十一:现在,GridView有了一个页脚行

  图十一中的页脚行并不明显,因为它的背景是白色的。让我们在Styles.css中创建一个名为FooterStyle的CSS类,用它来指定一个深红色的背景,并在DataWebControls主题中配置GridView.skin这个皮肤文件(Skin file)以将此CSS类分配给此GridView的FooterStyle的CssClass属性。如果你需要复习一下皮肤和主题的相关内容,请参考“使用ObjectDataSource显示数据”。

先给Styles.css添加以下的CSS类:

.FooterStyle
{
  background-color: #a33;
  color: White;
  text-align: right;
}

  FooterStyle这个CSS类跟HeaderStyle类是一样的,只是HeaderStyle的背景色要深一点且文本是粗体显示的而已。此外,页脚的文本是右对齐的,而页眉的文本是居中的。然后,为了将这个CSS类关联到每一个GridView的页脚上,在DataWebControls主题中打开GridView.skin文件并设置FooterStyle的CssClass属性。作了这个添加之后,文件的标记代码应该是这个样子:

<asp:GridView runat="server" CssClass="DataWebControlStyle">
  <AlternatingRowStyle CssClass="AlternatingRowStyle" />
  <RowStyle CssClass="RowStyle" />
  <HeaderStyle CssClass="HeaderStyle" />
  <FooterStyle CssClass="FooterStyle" />
  <SelectedRowStyle CssClass="SelectedRowStyle" />
</asp:GridView>

就像下面这个屏幕截图所显示的那样,这个更改使页脚清晰的显示出来了。

在ASP.NET 2.0中操作数据之十五:在GridView的页脚中显示统计信息

图十二:GridView的页脚现在有了一个红红的背景色

第三步:计算统计数据

在显示了GridView的页脚之后,下一个面对我们的挑战就是如何计算统计数据。有两个计算统计信息的途径:

1.通过一个SQL查询——我们可以向数据库发出一个额外的查询来为某个特定的类别计算统计信息。SQL包含一系列的聚合函数,并由GROUP BY子句指定应该根据什么数据来进行统计。下面的SQL查询将会返回我们所需要的信息:

SELECT CategoryID, AVG(UnitPrice), SUM(UnitsInStock), SUM(UnitsOnOrder)
FROM Products
WHERE CategoryID = categoryID
GROUP BY CategoryID

 

当然,你也可能不喜欢直接在SummaryDataInFooter.aspx页面中直接执行这个查询,而是希望在ProductsTableAdapter 和ProductsBLL 中创建一个方法来干这个事情。

2.由于这些信息已经添加到GridView中了,所以可以直接计算——就像在“基于数据的自定义格式化”中讨论的那样,在GridView的数据绑定之后,GridView的RowDataBound事件处理方法会在添加每一行数据时被执行一次。为这个事件创建了事件处理方法之后,我们就可以保持一个累积的合计值了。在最后一行数据被绑定到DataGrid上之后,我们就有了一个合计值以及需要计算平均值的信息了。

  一般来说,我还是喜欢第二种方法的,因为它节省了一次到数据库的往返,而且要达到这个效果还需要在数据访问层和业务逻辑层中实现统计功能,不过话说回来了,其实两种办法都行的。在这本教程中,我们还是使用第二个办法吧,并使用RowDataBound事件处理方法来记录这个累积合计。

  给GridView新建一个RowDataBound事件处理方法,你可以在设计器中选择GridView,然后在属性窗口中点击那个带闪电符号的图标,找到RowDataBound事件并双击它就可以了。这样就会在SummaryDataInFooter.aspx页面的后置代码类中添加一个新的名为ProductsInCategory_RowDataBound的事件处理方法了。

protected void ProductsInCategory_RowDataBound
  (object sender, GridViewRowEventArgs e)
{
}

为了可以维护一个累积合计,我们需要在这个事件处理方法的外面定义一些变量。创建以下4个页面级的变量:

·_totalUnitPrice,类型为decimal

·_totalNonNullUnitPriceCount,类型为int

·_totalUnitsInStock,类型为int

·_totalUnitsOnOrder,类型为int

然后,在RowDataBound事件处理方法中写一些代码,使每一个数据行都可以增加这些变量的值。

// Class-scope, running total variables...
decimal _totalUnitPrice = 0m;
int _totalNonNullUnitPriceCount = 0;
int _totalUnitsInStock = 0;
int _totalUnitsOnOrder = 0;
protected void ProductsInCategory_RowDataBound(object sender,
 GridViewRowEventArgs e)
{
  if (e.Row.RowType == DataControlRowType.DataRow)
  {
    // Reference the ProductsRow via the e.Row.DataItem property
    Northwind.ProductsRow product =
     (Northwind.ProductsRow)
     ((System.Data.DataRowView)e.Row.DataItem).Row;
    // Increment the running totals (if they are not NULL!)
    if (!product.IsUnitPriceNull())
    {
      _totalUnitPrice += product.UnitPrice;
      _totalNonNullUnitPriceCount++;
    }
    if (!product.IsUnitsInStockNull())
      _totalUnitsInStock += product.UnitsInStock;
    if (!product.IsUnitsOnOrderNull())
      _totalUnitsOnOrder += product.UnitsOnOrder;
  }
} 

  在RowDataBound事件处理方法中,我们首先应该确保我们正在操作一个DataRow。一旦确定了是这么回事,e.Row中那个刚刚绑定到GridViewRow对象的Northwind.ProductsRow实例就可以赋值给product变量了。接着,累积合计就被当前产品的相关值(当然了,我们还是应该要确保它们不会含有一个数据库NULL值)增加了。我们同时记录了累积的UnitPrice合计以及非空UnitPrice记录的条数,因为平均价格是这两个数的商。

第四步:在页脚中显示统计数据

  计算了统计数据之后,最后一个步骤就是在GridView的页脚上显示它了。同样,这个任务也可以通过RowDataBound事件处理方法来完成。回忆一下RowDataBound事件处理方法,它会在每一行绑定到GridView的时候被触发,页脚行也不例外。因此,我们可以扩展我们的事件处理方法,让它可以通过如下的代码来在页脚行中显示数据:

protected void ProductsInCategory_RowDataBound
  (object sender, GridViewRowEventArgs e)
{
  if (e.Row.RowType == DataControlRowType.DataRow)
  {
   ... Increment the running totals ...
  }
  else if (e.Row.RowType == DataControlRowType.Footer)
  {
   ... Display the summary data in the footer ...
  }
}

  因为页脚行是在所有的数据行都已经添加之后才添加到GridView中的,所以我们可以相信在将统计数据显示在页脚中之前,累积合计值都已经计算完毕了。最后一步就是将这些值放到页脚的单元格中了。

  要在页脚的特定单元格中显示文本,可以使用use e.Row.Cells[index].Text = value,单元格的索引是从0开始的。下面的代码计算了平均价格(总的价格除以产品的数量)并将其与库存量和订货量一起显示到GridView页脚的相应单元格中。

protected void ProductsInCategory_RowDataBound
  (object sender, GridViewRowEventArgs e)
{
  if (e.Row.RowType == DataControlRowType.DataRow)
  {
   ... <i>Increment the running totals</i> ...
  }
  else if (e.Row.RowType == DataControlRowType.Footer)
  {
   // Determine the average UnitPrice
   decimal avgUnitPrice = _totalUnitPrice / (decimal) _totalNonNullUnitPriceCount;
   // Display the summary data in the appropriate cells
   e.Row.Cells[1].Text = "Avg.: " + avgUnitPrice.ToString("c");
   e.Row.Cells[2].Text = "Total: " + _totalUnitsInStock.ToString();
   e.Row.Cells[3].Text = "Total: " + _totalUnitsOnOrder.ToString();
  }
}

图十三展示了添加了这段代码之后这个报表的样子。注意ToString("c")是如何让平均价格这个统计信息格式化成货币形式的。

在ASP.NET 2.0中操作数据之十五:在GridView的页脚中显示统计信息

图十三:现在的效果(译者注:估计原文这里又弄错了,写得跟图十二的一样。这里的原文是“Figure 13: The GridView's Footer Row Now Has a Reddish Background Color”,图十二的一样。这里的原文是“Figure 13: The GridView's Footer Row Now Has a Reddish B的原文是“Figure 12: The GridView's Footer Row Now Has a Reddish Background Color”)

总结

  显示统计信息是一个常见的报表需求,而GridView控件可以在页脚行中包含这样的信息,而且它将这个操作变得非常简单。当GridView的ShowFooter属性被设置为true时就可以显示页脚行了,并且通过RowDataBound事件处理方法可以将这些信息显示在它的不同的单元格中。可以通过重新查询数据库的数据,也可以在ASP.NET页面的后置代码类中通过编程的方式来计算这些统计数据。

  本节教程结束了我们关于GridView、DetailsView以及FormView控件的自定义格式化的学习。接下来的教程中,我们会开始一个使用这些控件来进行增删改操作的探索。

编程愉快!

关于作者

Scott Mitchell,著有六本ASP/ASP.NET方面的书,是4GuysFromRolla.com的创始人,自1998年以来一直应用微软Web技术。Scott是个独立的技术咨询顾问,培训师,作家,最近完成了将由Sams出版社出版的新作,24小时内精通ASP.NET 2.0。他的联系电邮为mitchell@4guysfromrolla.com,也可以通过他的博客http://ScottOnWriting.NET与他联系。

 
标签: ASP.NET GridView 页脚
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • [VB][ASP.NET]FileUpload控件「批次上传 / 多档
    FileUpload控件「批次上传 / 多档案同时上传」的范例 (VB语法) http://www.dotblogs.com.tw/mis2000lab/archive/2008/05/14/3986.aspx    FileUpload控件真的简单好用,不使用它来作批次上传,却要改用别的方法,实在不聪明。要用就一次用到底,公开File
    02-10
  • 使用WebClient自动填写并提交ASP.NET页面表单的源代码
    使用WebClient自动填写并提交ASP.NET页面表单的
    转自:http://www.cnblogs.com/anjou/archive/2007/03/07/667253.html 在.NET中通过程序填写和提交表单还是比较简单。比如,要提交一个如下图所示的登录表单:           填写和提交以上表单的代码如下:       // 要提交表单的URI字符串
    02-09
  • asp.net mvc多条件+分页查询解决方案
    


            
asp.net mvc多条件+分页查询解决方案
    asp.net mvc多条件+分页查询解决方案
    http://www.cnblogs.com/nickppa/p/3232535.html开发环境vs2010css:bootstrapjs:jquery    bootstrap paginator原先只是想做个mvc的分页,但是一般的数据展现都需要检索条件,而且是多个条件,所以就变成了MVC多条件+分页查询因为美工不是很好,所以用的是
    02-09
  • ASP.NET操作Cookies的问题(Bug or Not)
    以下存和取都是在不同的页面中,如果是在同一个页面也没必要用cookies了。 Test1: 给Cookies赋值: const string AAA="aaa"; Response.Cookies[AAA].Value = "111;222;333"; 取值: string value = Request.Cookies[AAA].Value; // value为111 Test2: 给Cooki
    02-09
  • Asp.Net Core 自定义验证属性
      很多时候,在模型上的验证需要自己定义一些特定于我们需求的验证属性。所以这一篇我们就来介绍一下怎么自定义验证属性。  我们来实现一个验证邮箱域名的自定义验证属性,当然,最重要的是需要定义一个继承自ValidationAttribute的类,然后在实现其IsVal
    02-09
  • Asp.Net 之 枚举类型的下拉列表绑定
    有这样一个学科枚举类型:/// 学科 /// /summary public enum Subject {None = 0,[Description("语文")]Chinese = 1,[Description("数学")]Mathematics = 2,[Description("英语")]English = 3,[Description("政治")]Politics = 4,[Description("物理&qu
    02-09
  • [ASP.NET笔记] 1.Web基础知识
         1:http协议:     2:web服务器:     3:静态网页的概念     4:动态网页的概念       http协议:http(hypertext transfer protocol) 即超文本传输协议,这个协议是在internet上进行信息传送的协议任何网页之间要相互沟通,必须要尊循
    02-09
  • ASP.NET邮件发送 .net 发送邮件
      今天做了个ASP.NET做发送邮件功能,发现QQ邮箱好奇怪,当你用QQ邮箱做服务器的时候什么邮件都发送不出去(QQ邮箱除外)。而且爆出这样的错误:"邮箱不可用。 服务器响应为: Error: content rejected.http://mail.qq.com/zh_CN/help/content/rejectedmail.ht
    02-09
  • 由ASP.NET Core根据路径下载文件异常引发的探究
    前言    最近在开发新的项目,使用的是ASP.NET Core6.0版本的框架。由于项目中存在文件下载功能,没有使用类似MinIO或OSS之类的分布式文件系统,而是下载本地文件,也就是根据本地文件路径进行下载。这其中遇到了一个问题,是关于如何提供文件路径的,通
    02-09
  • ASP.NET的运行原理与运行机制 ASP.NET的开发模式包括
    ASP.NET的运行原理与运行机制 ASP.NET的开发模
    在Asp.net4和4.5中,新增了WebPages Framework,编写页面代码使用了新的Razor语法,代码更加的简洁和符合Web标准,编写方式更接近于PHP和以前的Asp,和使用WebForms这种模仿Windows Form编程方式有了很大不同,不再有大量控件和控件生成的大量不够灵活的代码
    02-09
点击排行