【ASP.NET Step by Step】之十一至十五 Custom Formatting Based Upon Data

Chapter11 Custom Formatting Based Upon Data

1. 绑定数据到控件事件过程

不管是从数据控件或编码填充数据到DataSource属性并调用其DataBind()方法。以下几种事件将触发 

  1. DataBinding事件触发
  2. 数据绑定到数据绑定控件
  3. DataBound事件触发

2. DetailsView如何实现当UnitPrice大于75的行,用粗体,italic字体显示出来?
用DetailsView的DataBound事件

protected   void  ExpensiveProductsPriceInBoldItalic_DataBound( object  sender, EventArgs e)

{
    
//  Get the ProductsRow object from the DataItem property
    Northwind.ProductsRow product 
=  (Northwind.ProductsRow)((System.Data.DataRowView) ExpensiveProductsPriceInBoldItalic.DataItem).Row;

    
if  ( ! product.IsUnitPriceNull()  &&  product.UnitPrice  >  75m)
    {
        
//  TODO: Make the UnitPrice text bold and italic
        ExpensiveProductsPriceInBoldItalic.Rows[ 4 ].Font.Bold  =   true ;
        ExpensiveProductsPriceInBoldItalic.Rows[
4 ].Font.Italic  =   true ;
        或者设置CSS的方法
    }
}


注意DataItem属性,见下面的解释。

而对于FormView控件, 因为没有行的集合,是静态HTML,web控件的集合,所以,它的方法是这样的
页面中

asp:FormView ID="LowStockedProductsInRed" runat="server" DataKeyNames="ProductID"
    DataSourceID="ObjectDataSource1" AllowPaging="True" EnableViewState="False">         
    
< ItemTemplate >
        
< b > Product: </ b >
        
< asp:Label  ID ="ProductNameLabel"  runat ="server"  Text ='<%# Bind("ProductName") %>' >
        
</ asp:Label >< br  />
        
< b > Units In Stock: </ b >
        
< asp:Label  ID ="UnitsInStockLabel"  runat ="server"  Text ='<%# Bind("UnitsInStock") %>' >
        
</ asp:Label >
    
</ ItemTemplate >
</ asp:FormView >


方法是在ItemTempelete中使用FindControl(“controlID”)方法查找控件, 这里要找的ControlID就是 上面的 UnitsInStockLabel

  protected   void  LowStockedProductsInRed_DataBound( object  sender, EventArgs e)
{
        
//  Get the ProductsRow object from the DataItem property
        Northwind.ProductsRow product  =  (Northwind.ProductsRow)((System.Data.DataRowView)LowStockedProductsInRed.DataItem).Row;

        
if  ( ! product.IsUnitsInStockNull()  &&  product.UnitsInStock  <=   10 )
        {
            Label unitsInStock 
=  (Label)LowStockedProductsInRed.FindControl( " UnitsInStockLabel " ); 

            
if  (unitsInStock  !=   null )
            {
                unitsInStock.CssClass 
=   " LowUnitsInStockEmphasis " ;
            }
        }
    }

 

GridView事件触发过程

对于GridView,
     1. DataBinding事件触发 
     2. 数据绑定到数据绑定控件
对于每一行数据..
a.       创建GridViewRow
b.       触发RowCreated 事件
c.       绑定数据到GridViewRow
d.       触发RowDataBound事件
e.       添加GridViewRow到Rows 集合
     3. DataBound事件触发

注意: GridView由各种类型不同的行组成

  • DataRow – a row that is bound to a record from the GridView's DataSource
  • EmptyDataRow – the row displayed if the GridView's DataSource is empty
  • Footer – the footer row; shown if the GridView's ShowFooter property is set to true
  • Header – the header row; shown if the GridView's ShowHeader property is set to true (the default)
  • Pager – for GridView's that implement paging, the row that displays the paging interface
  • Separator – not used for the GridView, but used by the RowType properties for the DataList and Repeater controls, two data Web controls we'll discuss in future tutorials

所以在处理的时候要先进行check

protected   void  HighlightCheapProducts_RowDataBound( object  sender, GridViewRowEventArgs e){
        
//  Make sure we are working with a DataRow
         if  (e.Row.RowType  ==  DataControlRowType.DataRow)

            
//  Get the ProductsRow object from the DataItem property
            Northwind.ProductsRow product  =  (Northwind.ProductsRow)((System.Data.DataRowView)e.Row.DataItem).Row;

            
if  ( ! product.IsUnitPriceNull()  &&  product.UnitPrice  <  10m)
                e.Row.CssClass 
=   " AffordablePriceEmphasis "
}

 

DataItem

Northwind.ProductsRow product=(Northwind.ProductsRow)((System.Data.DataRowView) ExpensiveProductsPriceInBoldItalic.DataItem).Row;
Northwind.ProductsRow product = (Northwind.ProductsRow)((System.Data.DataRowView)e.Row.DataItem).Row;

DetailView和FormView是通过ForView1.DataItem, DetailView1.DataItem得到DataRowView object,
而GridView是通过参数e.Row得到DataRowView object,
DataSource的某条记录绑定到GridViewRow,DataRowView object是对应于这条记录的。它的Row返回这条强类型记录,例如返回ProductsRow

Chapter12 Using TemplateFields in the GridView Control

TemplateFields的应用
     1. 将两个数据合并到一个列中,姓和名字展示在一栏里
     2.
用一个Web控件来展示数据,而不是用一个简单的文本,例如日历控件
     3. 展示数据的元数据,统计每个员工工作多久了
 

后台代码,接受一个EmployeesRow参数,计算到现在的间隔天数

protected   string  DisplayDaysOnJob(Northwind.EmployeesRow employee)
{
        
if  (employee.IsHireDateNull())
        {
            
return   " Unknown " ;
        }
        
else
        {
            TimeSpan ts 
=  DateTime.Now.Subtract(employee.HireDate);
            
return  ts.Days.ToString( " #,### " );
        }
}

前台代码,调用前台的函数DisplayDaysOnJob,参数是当前行的EmployeesRow
< asp:TemplateField  HeaderText ="Days On The Job" >
   < ItemTemplate >

     <%# DisplayDaysOnJob((Northwind.EmployeesRow) ((System.Data.DataRowView) Container.DataItem).Row) %>
   <ItemTemplate>
</asp:TemplateField>

Container.DataItem returns a DataRowView object corresponding to the DataSource record bound to the GridViewRow.
Its Row property ((System.Data.DataRowView) Container.DataItem).Row
returns the strongly-typed Northwind.EmployeesRow, which is passed to the DisplayDaysOnJob method.

除了传递一个EmployeesRow的实例,其实我们也可以仅仅传递HireDate的值,使用<%# DisplayDaysOnJob(Eval("HireDate")) %>就可以了。不过呢,Eval方法将返回一个object类型,所以我们就必须要修改DisplayDaysOnJob方法的签名以使其可以接受一个object类型的参数。我们不能将Eval("HireDate")调用的结果隐式的转换成一个DateTime类型,因为Employees表的HireDate字段是允许为空的。因此,我们需要使DisplayDaysOnJob方法可以接受一个object类型的参数,并判断这个参数是不是空值(我们可以使用Convert.IsDBNull(objectToCheck)来完成这个验证工作),然后再进行后面的操作。

对比这个:将discontinued显示为"Yes"/"No", 而不是Checkbox
protected string DisplayDiscontinuedAsYESorNO(bool discontinued)
{
        if (discontinued)        {            return "yes";        }
        else       {            return "no";        }
}
对比上面的相关内容,传递给格式化方法的参数可能是空值,所以我们需要在访问雇员的HiredDate之前对它进行空值检查。这样的检查在这里却是不需要的,因为Discontinued字段永远不会是空值。此外,这也是为什么这个方法接受的是一个布尔值而不是ProductsRow实例或object类型的参数的原因 

1 < asp:TemplateField  HeaderText ="Discontinued"  SortExpression ="Discontinued" >
2      < ItemTemplate >
3          <% # DisplayDiscontinuedAsYESorNO((bool) Eval("Discontinued"))  %>
4      </ ItemTemplate >
5 </ asp:TemplateField >
6

 

Chapter13 Using the FormView's Templates

这一章没什么意思,在显示一个单独的记录的时候,FormView提供了一种更加复杂的的呈现方式。而不想DetailView和GridView一样都是一个个格子。

Chapter14 Displaying Summary Information in the GridView's Footer

这一章讲了怎么在GridView的Footer里显示统计信息,总量,平均价格等。
统计信息两种方法:
1. SQL语句

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


2. 数据绑定之后,计算

 1 //  类范围,累积合计的变量……
 2 decimal  _totalUnitPrice  =  0m;
 3 int  _totalNonNullUnitPriceCount  =   0 ;
 4 int  _totalUnitsInStock  =   0 ;
 5 int  _totalUnitsOnOrder  =   0 ;
 6
 7 protected   void  ProductsInCategory_RowDataBound( object  sender, GridViewRowEventArgs e)
 8 {
 9    if (e.Row.RowType == DataControlRowType.DataRow)
10    {
11        // 通过e.Row.DataItem 属性引用ProductsRow
12        Northwind.ProductsRow product = (Northwind.ProductsRow)((System.Data.DataRowView)e.Row.DataItem).Row;
13
14        // 增加累积合计(如果它们不为NULL的话!)
15        if (!product.IsUnitPriceNull())
16        {
17            _totalUnitPrice += product.UnitPrice;
18            _totalNonNullUnitPriceCount++;
19        }

20
21        if (!product.IsUnitsInStockNull())
22            _totalUnitsInStock += product.UnitsInStock;
23
24        if (!product.IsUnitsOnOrderNull())
25            _totalUnitsOnOrder += product.UnitsOnOrder;
26    }

27}

在页脚中显示统计数据,可以仍然通过RowDataBound事件,只要判断是否是Footer就行了

 1 protected   void  ProductsInCategory_RowDataBound( object  sender, GridViewRowEventArgs e)
 2 {
 3    if (e.Row.RowType == DataControlRowType.DataRow)
 4    {
 5      //……增加累积合计……
 6    }

 7    else if (e.Row.RowType == DataControlRowType.Footer)
 8    {
 9      // 确定平均单价
10      decimal avgUnitPrice = _totalUnitPrice / (decimal) _totalNonNullUnitPriceCount;
11
12      // 在相应的单元格中显示统计数据
13      e.Row.Cells[1].Text = "Avg.: " + avgUnitPrice.ToString("c");
14      e.Row.Cells[2].Text = "Total: " + _totalUnitsInStock.ToString();
15      e.Row.Cells[3].Text = "Total: " + _totalUnitsOnOrder.ToString();
16    }

17}

 

你可能感兴趣的:(asp.net)