从总体上讲,ASP.NET数据绑定模型可以分为三部分:数据绑定表达、传统数据源、数据源控件。
可用的数据源
在ASP.NET中,任何一个暴露IEnumerable接口的对象,都是有效的可绑定数据源。IEnumerable接口定义了一个用于枚举数据源内容的方法:
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
具体来讲,我们可以将Web控件绑定到以下类上:
1. ADO.NET容器类(如:DataSet、DataTable、DataView)
2. 数据读取器
3. 自定义的集合、字典、数组
DataSet和DataTable类事实上没有实现IEnumerable或任何继承于它的接口。然而,这些类在内部有数据存储集合,这些集合可通过一个中间接口(IListSource)的方法进行访问,这使DataSet和DataTable类看上去好像被实现为集合一样。
Web页面和Windows桌面应用程序的数据绑定工作方式不同。Web和窗体有同类的数据源对象,但数据读取器是个例外。我们只能将数据读取器绑定到ASP.NET控件。同样,只有Windows窗体控件才能绑定到DataViewManage类的实例上。
DataSet类可以包含若干张表,但每次只有一个与标准的ASP.NET数据绑定控件关联。如果将控件绑定到DataSet上,还需设置其他属性来选择该DataSet对象中的某张表。
数据绑定属性
ASP.NET中有两大类数据绑定控件:列表控件和迭代控件。列表控件使用固定模板显示数据源中的每条记录。迭代控件更灵活,使我们能够显式地定义重复显示的模板,以及其他直接影响控件最终布局的模板。
所有的数据绑定控件都实现了DataSource和DataSourceID等属性。
ListControl为列表控件的基类,BaseDataList为迭代控件的基类。
DataSource属性
DataSource属性使我们能够指定控件要链接的数据源对象。我们可以调用DataBind方法激活控件的数据绑定。该方法执行时,控件才会实现地从关联的数据源加载数据。
DataSource属性被声明为object类型,可以接受任何实现IEnumerable或IListSource接口的对象。
只有DataSet和DataTable实现了IListSource接口。
数据绑定控件的DataSource属性一般以编程方式设置,但也可采用声明方式:
< asp:DropDownList runat = " server " id = " theList " DataSource = " <%# GetData() %> " />
本例中,GetData是代码隐藏页面类的一个公共或受保护成员,它能返回可绑定对象。
数据绑定控件如何判断自己实际绑定到哪种对象上?是集合、数据读取器还是DataTable?所有标准的数据绑定控件都通过IEnumerable接口来进行操作。因此,任何要绑定到DataSource的对象都要进行规范化,统一实现IEnumerable接口。在某些情况下,这个过程无非是将对象转换为IEnumerable接口类型。但在其他情况下,还需执行一些操作赋值给DataMember确定相应的已命名数据集合。
DataSourceID属性
ASP.NET 2.0属性引入了DataSourceID属性,用于获取或设置数据源组件的ID。所有的数据绑定控件都有这个DataSourceID,它与DataSource属性是互斥的,如果都设置,控件将会在运行时抛出异常。
DataMember属性
DataMember属性用于获取或设置在绑定数据源时要抽取的数据集合的名称。
若将DataSource设置为DataSet对象,该属性则可用于指定DataTable的名称。示例代码:
DataSet data = new DataSet();
SqlDataAdapter adapter = new SqlDataAdapter(cmdText, connString);
adapter.Fill(data);
grid.DataMember = " Table " ;
grid.DataSource = data;
grid.DataBind();
DataTextField属性
列表控件一般要使用DataTextField属性,它用于指定列表控件中元素显示的文本取自哪个数据绑定项。
列表控件能够对DataTextField属性设置的字段内容自动进行格式化处理。格式表达式由DataTextFormatString属性指定。
DataValueField属性
DataValueField用于指定列表控件中元素的值取自哪个数据绑定项。
示例代码:
CustomerList.DataMember = " Table " ;
CustomerList.DataTextField = " companyname " ;
CustomerList.DataValueField = " customerid " ;
CustomerList.DataSource = data;
CustomerList.DataBind();
如果DataValueField为空,则会用DataTextField属性的值替代。
AppendDataBoundItems属性
ASP.NET 2.0引入该布尔类型的属性指明数据绑定项是追加到控件现有内容中,还是将内容改写。默认为false,表明数据绑定内容会取代现有内容。
DataKeyField属性
该属性用于获取或设置指定数据源中的键字段。在使用DataGrid一类的控件时,该属性指示的字段可以标识其中的记录。
仅当该字段在源数据有唯一约束时,记录的标识符才有效。
DataKeyField对应于数组类型的DataKeys属性。
ASP.NET新的GridView控件将DataKeyField扩展为字符串数组,并将其重命名为DataKeyNames。
列表控件
列表控件包括DropDownList、CheckBoxList、RadioButtonList、ListBox、BulletedList,这些控件都继承于ListControl类。
DropDownList控件
DropDownList控件的DataTextField和DataValueField属性不接受表达式,只能设置纯文本的列名。
CheckBoxList控件
CheckBoxList控件不提供被选择项的列表属性,那如何获取被选择项呢?代码如下所示:
foreach (ListItem item in chkList.Items)
{
if (item.Selected)
{
// 被选中项处理
}
}
RadioButtonList控件
SelectedItem属性会以ListItem对象的形式返回被选择的元素。但注意,没有什么可确保在任何时候都有被选择项。所以,在访问该控件的SelectedItem时应该非常小心,它有可能为空。
ListBox控件
ListBox控件允许单选或多选,通过Items集合暴露其内容。
上述所有列表控件都支持SelectedIndexChanged事件,在列表的选择项更改并回发给服务器后该事件会被触发。
BulletedList控件
BulletedList控件的编程接口是围绕着<ul>和<ol>HTML标签构建的。
迭代控件
迭代控件提供了一套基于模板的机制来创建自定义的用户页面。Repeater、DataList、DataGrid都是迭代控件。模板的定义需要使用一些声明式的代码,如果要以编程方式完成,则要求编写一个实现ITemplate接口的类。
Repeater控件
Repeater类实现了标记式的接口INamingContainer,能够用作命名容器,下表是该控件的主要属性:
Repeater会通过枚举绑定数据源中的所有数据项,填充Items集合。对于每个数据绑定项,它将创建RepeaterItem对象,并将其添加到Items集合中。Repeater代表要显示的元素,RepeaterItem属性的内容包括绑定的数据项、索引值、当前数据项的类型。下面是一个Repeater示例:
< asp:Repeater ID = " Repeater1 " runat = " server " ><!-- 页眉模板 -->
< HeaderTemplater >
< h2 > We have customers in the following cities </ h2 >
< hr />
</ HeaderTemplater ><!-- 分隔符模板 -->
< SeparatorTemplater >
< hr noshade style = " border:dashed 1px blue " />
</ SeparatorTemplate ><!-- 数据项呈现模板 -->
< ItemTemplate >
<% # Eval( " City " ) %>& nbsp; & nbsp; < b ><% # Eval( " Country " ) %></ b >
</ ItemTemplate ><!-- 页脚模板 -->
< FooterTemplate >
< hr />
<% # CalcTotal() %> cities
</ FooterTemplate >
</ asp:Repeater >
后台代码:
data = new DataTable();
SqlDataAdapter adapter = new SqlDataAdapter( " Select distinct country, city
From customers Where country = @TheCountry " , connString);
adapter.SelectCommand.Parameters.AddWithValue( " @TheCountry " , Countries.SelectedValue);
adapter.Fill(data);
Repeater1.DataSource = data;
Repeater1.DataBind();
在所有模板中,只有ItemTemplate和AlternatingItemTemplate可以绑定数据。这两个模板能重复应用到数据源中的每一项。我们需要一种从模板中访问数据项公共属性的机制。Eval方法接受属性的名称,返回的是它所指代的内容。
DataList控件
DataList是一种数据绑定控件,其功能介于Repeater和DataGrid控件间。它在某些方面要胜于Repeater,主要是在图形布局方面。DataList支持方向性呈现,这表明,该控件能够在垂直方向上顺序显示,也能在指定的列数水平显示。它还提供节一些快捷方式来获取与当前数据行关联的键值,对选择有内键的支持。
DataList对生成的结果有一定的限制:HTML标记不能跨出模板,且最终必须以HTML表格的形式输出。
除充当命名容器,DataList还实现了IRepeatInfoUser接口。该接口定义的属性和方法是所有列表控件为罗列列表项必须实现的接口。该接口被CheckBoxLis和RadioButtonList控件支持。下面的代码重写了上一个例子:
< asp:DataList ID = "DataList 1 " runat = " server " RepeatColumns="5" GridLines="Both" ><FooterStyle Font-Bold="true" ForeColor="blue" />
< HeaderTemplater >
< h2 > We have customers in the following cities </ h2 >
< hr />
</ HeaderTemplater ><!-- 数据项呈现模板 -->
< ItemTemplate >
<% # Eval( " City " ) %>& nbsp; & nbsp; < b ><% # Eval( " Country " ) %></ b >
</ ItemTemplate ><!-- 页脚模板 -->
< FooterTemplate >
< hr />
<% # CalcTotal() %> cities
</ FooterTemplate >
</ asp:DataList >