[ 1 ]————–使用DatatSource control访问数据
1. 什么是数据(Data) : xml, database, 提供某些interface的class,如dataset.

2. 什么是data source controls:
封装了数据来源的差异,使用declarative syntax来配置,

3. GridView等数据显示控件如何使用data source control.
GridView.DataSourceID = DataSources.ID

3.1. 使用SqlDataSource
优点:简单, 缺点:增加了页面的复杂度,在页面上绑定数据访问逻辑.
配置DataSource时会设置SELECT,INSERT, UPDATE, 和 DELETE Statement,

<asp:SqlDataSource ID=”productsDataSource” Runat=”server” 
“SelectCommand=”SELECT [ProductID], [ProductName], ” & _ 
“[QuantityPerUnit], [UnitPrice], [UnitsInStock] ” & _ 
“FROM [Products]” 
ConnectionString= 
“<%$ ConnectionStrings:NWConnectionString %>” 
DataSourceMode=”DataReader”> 
</asp:SqlDataSource>

3.2 使用ObjectDataSource
提供一个Data Access Layer (DAL).
注意,DAL和数据实体可以不在同一个class中,即可以有Product 和 ProductDAL两个class

在配置ObjectDataSource时指定执行Select, Update, delete, Insert操作的方法名.

3.3 使用 XmlDataSource

[ 2 ]—————Formatting the GridView
Format 相关的property:
BackColor, Font, ForeColor
HeaderStyle, RowStyle, AlternatingRowStyle, FooterStyle

使用Smart Tag上的Auto Formatting, 此功能只提供整体的配色方案

使用Smart Tag上的Edit Columns, 对单独的column进行format.
使用Bound Field的DataFormatString 来格式化输出,比如
日期column的DataFormatString: DataFormatString=”{0:yyyy.MM.dd}”
注意,出于安全上的考虑,还要设置HtmlEncode=”false”

使用Skin
一个project的Theme的目录结构
/app_themes/<ThemeName>/ .css .skin .Image

Theme : 多个Skin的集合.

Skin : 包含了某些control的外观的文件.
Skin的格式:

<!– Default Skin –> 
<asp:GridView runat=”server” Font-Name=”Arial” /> 
<asp:GridView runat=”server” SkinID=”Professional” Font-Name=”Verdana” 
Font-Size=”10pt” Cellpadding=”4″ 
HeaderStyle-BackColor=”#444444″ 
HeaderStyle-ForeColor=”White” 
AlternatingRowStyle-BackColor=”#dddddd” /> 
<asp:GridView runat=”server” SkinID=”Fun” Font-Name=”Comic Sans MS” 
Font-Size=”13pt” BackColor=”Khaki” 
AlternatingRowStyle-BackColor=”Tan” 
HeaderStyle-BackColor=”SaddleBrown” 
HeaderStyle-ForeColor=”White” 
HeaderStyle-Font-Bold=”True”/>

使用Skin

<%@ Page Language=”C#” StyleSheetTheme=”<Theme Name>” %> 
… 
<asp:GridView ID=”GridView1″ Runat=”server” SkinID=”<Skin Name>”>

根据数据动态Formatting the GridView,比如根据数据而使用不同的颜色.

void productsGridView_RowDataBound(object sender, GridViewRowEventArgs e) 
{ 
if (e.Row.RowType == DataControlRowType.DataRow) 
{ 
// determine the value of the UnitsInStock field 
int unitsInStock = Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, “UnitsInStock”)); 
if (unitsInStock == 0) 
{ 
// color the background of the row yellow 
e.Row.BackColor = Color.Yellow; 
} 
} 
}


RowDataBound event 在每个row被生成时触发,由于包含HeaderRow,所以使用e.Row.RowType来判断是否
需要fromatting.关键在于如何得到row的某个field:
DataBinder.Eval(e.Row.DataItem, “UnitsInStock”)

[ 3 ]—————Master/Detail
典型用法: ComboBox(DropDownList) + GridView
1. 把DropDownList的DataValueField设置为一个Field的Name 如”ProductID”, 意味着当DropDownList的一个Item被选中时,
DropDownList的SelectedValue等于字段”ProductID”的值,
2. 设置GridView对应的SqlDataSource的<SelectParameters>
指定使用DropDownList的SelectedValue属性来作为查询的条件.

<asp:SqlDataSource SelectCommand=”SELECT * FROM [OrderDetails] WHERE ([ProductID] = @ProductID)” ConnectionString=”…”> 
<SelectParameters> 
<asp:ControlParameter Name=”ProductID” Type=”Int32″ ControlID=”productSelector” PropertyName=”SelectedValue”> 
</asp:ControlParameter> 
</SelectParameters> 
</asp:SqlDataSource>

使用DAL显示 Master/Detail 数据, 关键在于配置ObjectDataSource,指定其SelectMethod

<asp:ObjectDataSource ID=”orderDetailsForProduct” 
Runat=”server” TypeName=”OrderDetailDAL” 
SelectMethod=”GetOrderDetailsByProductID”> 
<SelectParameters> 
<asp:ControlParameter Name=”productID” Type=”Int32″ 
ControlID=”productSelector” 
PropertyName=”SelectedValue”></asp:ControlParameter> 
</SelectParameters> 
</asp:ObjectDataSource>

[ 4 ]—————Paging and Soring
SqlDataSource 中的Paging and Soring只需要设置GridView的 AllowSorting=”True” 和AllowPaging=”True”
注意:
SqlDataSource 可以返回DataReader或DataSet,次行为可通过设置DataSourceMode属性来指定,
Default值为DataSet,如果要生成一个可”分页”的GridView, 必须使用DataSet.可”排序”的GridView
可以使用DataSet和DataReader,但使用DataReader时必须从一个接受sort expression的Stored procedure
中返回数据.
使用SqlDataSource的缺点是GridView 只能使用 default paging model, 即SqlDataSource会返回所有的数据.

ObjectDataSource 中的Paging and Soring
要支持 分页 ,DAL class的要多提供一个接受两个int参数的SELECT method ,
GetProducts(maximumRows, startRowIndex)
第一个参数表示返回的记录数, 第二个参数表示起始的row index.

要支持排序,DAL class的要多提供下列函数

GetProducts(SortExpression) //返回排序后的所有记录 
GetProducts(maximumRows, startRowIndex, SortExpression) //排序 + 分页

然后需要设置ObjectDataSource的下列属性:

<asp:ObjectDataSource ID=”productsDataSource” Runat=”server” TypeName=”ProductDAL” 
EnablePaging=”True” 
SortParameterName=”SortExpression” 
SelectMethod=”GetProducts” 
SelectCountMethod=”TotalNumberOfProducts”> 
</asp:ObjectDataSource>

ObjectDataSource的MaximumRowsParameterName 属性和StartRowIndexParameterName属性一般不用指定,
MaximumRowsParameterName缺省对应maximunRows, StartRowIndexParameterName缺省对应startRowIndex.

显示分页信息:

<i>You are viewing page<%=productsGridView.PageIndex + 1%>of<%=productsGridView.PageCount%></i>

[ 5 ]—————Displaying Images
文中推荐的做法是在数据库中存放一个PicureURL字段(形如”~/DisplayingImages/Images/Blue hills.jpg”)
真正的图片存放在file system中.
在进行data binding时,删除PicureURL字段, 添加一个ImageField, 并指定ImageField的DataImageUrlField
属性为”PicureURL”(datasource中包含picture url的字段名).

文中还用到了一个小技巧, 给GridView指定一个动态生成的data source:

DataTable GetData() 
{ 
… 
} <asp:GridView Runat=”server” DataSource=’<%# GetData() %>’ …> 
… 
</asp:GridView>[ 6 ]————–Working with TemplateFields 
GridView 可以使用不同的Column类型: 
BoundFiled, 显示DataSource的Fieled的内容 
ImageField, 通过DataSource的image url 字段来显示图片 
CommandField 显示command buttons. 
TemplateField, 可以显示HTML markup, web contorl, data-binding syntax

1.使用Function来自定义输出.

<%# FunctionName(parameter1, parameter2, …, parameterN) %> 
Sample: <%# ComputeSeniorityLevel(DateTime.Now - (DateTime)Eval(”HireDate”)) %> 
string ComputeSeniorityLevel(TimeSpan ts) 
{ 
int numberOfDaysOnTheJob = ts.Days; 
if (numberOfDaysOnTheJob >= 0 && numberOfDaysOnTheJob <= 1000) 
return “Newbie”; 
else if (numberOfDaysOnTheJob > 1000 && numberOfDaysOnTheJob <= 4000) 
return “Associate”; 
else if (numberOfDaysOnTheJob >= 4000 && numberOfDaysOnTheJob <= 8000) 
return “One of the Regulars”; 
else 
return “An Ol’ Fogey”; 
}


2.嵌入一个Web Control

<Columns> 
… 
<asp:TemplateField HeaderText=”Territories”> 
<ItemTemplate> 
<asp:BulletedList ID=”bltTerritories” Runat=”server” 
DataTextField=”TerritoryDescription” 
DataValueField=”TerritoryDescription”> 
</asp:BulletedList> 
</ItemTemplate> 
</asp:TemplateField> 
</Columns>


注意: 把DataTextField和DataValueField设置为DataSet的Field name
处理Gridview的RowDataBound event

<asp:GridView ID=”employeesGridView” OnRowDataBound=”employeesGridView_RowDataBound” />
void employeesGridView_RowDataBound(object sender, GridViewRowEventArgs e) 
{ 
// For each DataRow in the GridView, 
// programmatically access the BulletedList, filter 
// the DataView based on the GridView row’s 
// EmployeeID value and bind the filtered DataView 
// to the BulletedList 
if (e.Row.RowType == DataControlRowType.DataRow) 
{ 
BulletedList bl = (BulletedList)e.Row.FindControl(”bltTerritories”); 
territoryData.RowFilter = “EmployeeID = ” + ((DataRowView) e.Row.DataItem)[”EmployeeID”].ToString(); 
bl.DataSource = territoryData; 
bl.DataBind(); 
} 
}

[ 7.1 ]————–Master/Slave
一个Orders表和一个Order Details表
1. 用一个SqlDataSource取回Orders表中所有的数据.
2. 添加一个主GridView,绑定到SqlDataSource,并选中这个GridView的”Enable Selection”选项,
设置主GridView 的DataKeyNames属性,使得GridView的SelectValue属性会等于DataKeyNames属性
对应的字段的值.
3. 添加一个子SqlDataSource.设置其Select 方法的where参数的”Parameter Source”为Control,
ControlID为主GridView的ID.
4. 注意当主GridView分页时,子GridView不能正确显示数据,添加如下代码Fix
void orderGridView_PageIndexChanged(object sender, EventArgs e)
{
orderGridView.SelectedIndex = -1;
}

[ 7.2 ]—————- Summary to Detail
主GridView只显示部分数据, DetailsView显示所有的数据.
设置主GridView的DataKeyNames 属性为 CustomerID
设置DetailsView的SqlDataSource的FilterException属性为CustomerID=’{0}’

[ 8 ]——————–Summary Data in the Footer
处理RowDataBound事件

void detailsGridView_RowDataBound(object sender, GridViewRowEventArgs e) 
{ 
if (e.Row.RowType == DataControlRowType.DataRow) 
{ 
// add the UnitPrice and QuantityTotal to the running total variables 
priceTotal += Convert.ToDecimal(DataBinder.Eval(e.Row.DataItem, _ 
“UnitPrice”)); 
quantityTotal += Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, _ 
“Quantity”)); 
} 
else if (e.Row.RowType == DataControlRowType.Footer) 
{ 
e.Row.Cells[0].Text = “Totals:”; 
// for the Footer, display the running totals 
e.Row.Cells[1].Text = priceTotal.ToString(”c”); 
e.Row.Cells[2].Text = quantityTotal.ToString(”d”); e.Row.Cells[1].HorizontalAlign = _ 
e.Row.Cells[2].HorizontalAlign = HorizontalAlign.Right; 
e.Row.Font.Bold = true; 
} 
}

[ 9 ]———————Delete
在配置SqlDataSource时选中”Generate Insert, Update, and Delete Statements”check box.
如果使用了”Use optimistic concurrency”选项,当数据库中的数据和GridView中的当前数据
不一致时,对数据库的delete和update会失败.这个选项对应了SqlDataSource的ConflictDetection
属性的取值: CompareAllValues or OverwriteChanges.
设置GridView的 DataKeyNames 属性

GridView 提供了 RowDeleting Event:

e.Values, which provides data on the values of the row being deleted 
e.Cancel. Deleting from an ObjectDataSource


设置ObjectDataSource的ConflictDetection 属性.
如果使用了OverwriteChanges,需要提供方法

public static void DeleteMethod(int original_OrderID, int original_ProductID) 
{ 
… 
}

如果使用了CompareAllValues,需要提供方法:

public static void DeleteMethod(int original_OrderID, int original_ProductID, int original_Quantity, decimal original_UnitPrice) 
{ 
… 
}

Client Scitpt确认
注意:GridView’s CommandField does not include an OnClientClick property,故无法使用script.

<Columns> 
<asp:TemplateField><ItemTemplate> 
<asp:LinkButton ID=”LinkButton1″ Runat=”server” OnClientClick=”return confirm(’Are you sure you want to delete this record?’);” 
CommandName=”Delete”>Delete Order Line Item</asp:LinkButton> 
</ItemTemplate> 
</asp:TemplateField> 
</Columns>

[ 10 ]———————–Edit
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/GridViewEx10.asp
和Delete 类似

Customizing the Editing Interface!

GridView的SmartTag “Edit Columns”->Selected Fields->”Convert this field into a TemplateField”
使用GridView的SmartTag “Edit Templates”

1 . Validation
drag and drop the appropriate validation controls from the Toolbox into the EditItemTemplate

2. 在Combo中选择输入
Add a DropDownList to the EditItemTemplate and bind it to this SqlDataSource