Web 窗体页中的数据绑定介绍
与大多数窗体类型一样,Web 窗体页也允许通过将控件绑定到数据源来显示信息。但是,由于 Web 窗体页本身的特性以及 Web 编程的结构,Web 窗体页中的数据绑定与其他更传统的窗体(如 Windows 窗体)中的数据绑定略有不同。本主题提供有关 Web 窗体页中数据绑定、如何在 Web 应用程序中使用数据绑定以及在哪里能够找到有关 Web 窗体页中的数据绑定和数据访问的更多信息的背景信息。Web 窗体数据绑定:只读
Web 窗体页的数据绑定结构是基于 Web 应用程序中大多数数据访问是只读的这一观念——即,页上经常显示来自数据存储区的信息,但很少需要将数据写回到存储区。有很多类型的页提供只读数据,例如: 对其他 Web 页、产品等的搜索结果页。搜索结果页中的信息通常显示为到其他页的链接,并且很少需要用户输入要在数据库中保存的数据。 
提供运动成绩、天气信息等的页。 
门户页。许多门户页(例如 MSN 主页)允许用户自定义页面,方法是从显示的各种类型的信息中进行选择,这些信息包括新闻、财经信息、娱乐选项等。这些信息本身通常作为 XML 数据提供到页上,并且这些数据可以根据用户的首选项加以转换。 
向银行和经纪业客户提供帐户和金融交易信息的页。 
因为 Web 窗体数据绑定结构不执行更新(即,它不将数据从控件写回到数据源),所以您必须提供此逻辑。在 Web 窗体页中执行更新的逻辑将根据各种不同的因素而有很大的不同: 数据源是什么。 
是否通过使用数据集缓存数据。 
正在使用什么类型的控件——例如,控件是否显示多个记录(如在网格中),或者显示单个值(如在文本框中)。 
要使用什么类型的并发控件。 
因为有一些与从 Web 窗体页进行更新相关的不定因素,所以应该实现您自己的更新逻辑以满足您的 Web 窗体页和应用程序的具体要求。 绑定属性
Web 窗体页中的数据绑定是十分灵活的——可以将控件的任何属性绑定到数据。与之不同的是,在传统数据绑定中,通常将显示属性(例如,文本框的文本属性)绑定到数据源。 在 Web 窗体页中,数据源几乎可以是可用于该页的任何类型的信息——无论信息是来自数据库、来自 XML 文档、来自其他控件或进程、甚至是来自您自己执行的计算。 此外,Web 窗体数据绑定还使您可以将这些数据分配给任何控件的任何属性。因此,可以使用数据绑定执行多种操作,例如: 设置文本以在 TextBox、Label、Button、LinkButton 或其他控件中显示。 
设置链接控件的目标页(HREF 属性)。 
将 CheckBox 控件绑定到布尔值以直接设置该控件的选中状态。 
通过将 Image 控件的 ImageUrl 属性绑定到包含图形文件的 URL 或名称的数据库列来设置 Image 控件的图形。 
设置控件的颜色、字体或大小。这可以作为实现存储在数据库或其他数据存储区的用户首选项的十分有用的方法。 
换言之,数据绑定成为设置页上任何控件的任何运行时可访问属性的自动方法。绑定多记录和单值控件
控件可以支持两种类型的数据绑定: 多记录控件可以同时显示一个或多个数据记录,例如 Repeater、DataList、DataGrid Web 服务器控件和 HtmlSelect HTML 服务器控件。 
单值控件可以一次显示一个数据值。单值控件包括大多数 Web 服务器和 HTML 服务器控件,例如 TextBox、Label、HtmlInputText 和 HtmlAnchor 控件。 
注意 所有控件都允许您将单独的属性绑定到单个数据值。例如,DataList 控件一次可以显示多个记录,但可以将其 BackColor 属性绑定到单个数据值。
根据是绑定到多个记录还是绑定到单个数据值,数据绑定的工作方式也将有所不同。若要显示多个记录,您应该将多记录控件绑定到包含多个记录的数据源——数组、集合、数据表等。唯一的要求是数据源实现 IEnumerable 接口。默认行为是当发生数据绑定时,多记录控件依次通过数据源中的每一数据项。

解决方案 »

  1.   

    Web 窗体页的多记录和单值数据绑定
    某些 Web 窗体控件同时显示来自多个记录的值。这些控件包括 Repeater、DataList、DataGrid、ListBox、CheckBoxList 和 RadioButtonList Web 服务器控件,以及 HtmlSelect 控件。其他控件(例如 Label、TextBox、CheckBox 和 Hyperlink 控件)显示单值,单值在数据绑定术语中表示来自单个记录的值。多记录控件中的数据绑定
    若要绑定多记录控件,包括 Repeater、DataList、DataGrid、ListBox、RadioButtonList、CheckBoxList 和 HtmlSelect 控件,应设置指定要在哪里显示记录的属性。通常设置属性来指示: 包含要显示的记录的数据源(即容器)。典型的数据源是数据集。 
    数据成员(如果有多个可绑定成员),例如特定表的名称。 
    要显示的特定字段或列。这适用于诸如 ListBox 和 HtmlSelect 控件之类的控件,这些控件显示多个数据项,但每一项只有一个值。 
    注意 可以将多记录控件的各项属性分别绑定到单个数据值。例如,DataList 控件一次可以显示多个记录,但可以将其 BackColor 属性绑定到单个数据值。
    尽管通常绑定到数据集中的数据,但可以将多记录控件绑定到支持 IEnumerable 接口的几乎所有结构上。这包括以下结构: ArrayList 对象 
    集合 
    数据阅读器(OleDbDataReader 和 SqlDataReader 类型的对象) 
    DataView 对象 
    DataRow 对象 
    数据集中的 DataTable 对象 
    在数据绑定期间,多记录控件依次通过数据源,依次提取每一项。与依次提取每一数据项有关的情况取决于您所使用的多记录控件的类型。DataGrid 控件可以基于您指定的属性自动显示所有项或信息的子集。对比之下,Repeater 和 DataList 控件用作嵌入其模板的控件的容器,这些控件执行它们自己的数据绑定。绑定到单个数据值
    可以将单独的控件属性绑定到实际的任何信息上,这些信息可被解析成适合于所绑定的属性的单值。例如,一个十分常见的情况就是将 TextBox 控件的 Text 属性绑定到一个数据值上。若要执行此类绑定,不应使用显式数据绑定属性。而是获取所需的数据值并作为控件的属性值分配它。注意 不显示多个记录的控件(即,除 DataList、DataGrid 等之外的控件)不包括显式数据绑定属性。
    您可以使用“数据绑定表达式”将控件属性绑定到数据值。表达式可以引用数据集表或数据视图中的一行,或者可以引用其他控件的属性,或者可以引用几乎任何其他项。将属性值设置为此数据绑定表达式。在该页运行时,解析数据绑定表达式并将结果值分配给该属性。有关更多信息,请参阅 Web 窗体页的数据绑定表达式。如果使用数据绑定表达式来绑定到数据集中的数据,创建对一个特定记录的引用可能是不切实际的。数据集不维护指针或支持“当前记录”的概念,因此没有隐式的方式来指示要绑定到的记录。注意 这不同于 Windows 窗体。在 Windows 窗体中,置入窗体中的数据绑定结构维护其自己的指向数据集中记录的指针集,因此控件可绑定到“当前记录”类型。
    有几种方法来确定在绑定到单个数据值时要使用的记录: 创建一个数据视图,该数据视图筛选数据集表以只返回一个记录(例如,通过筛选唯一键)。然后可以将控件绑定到数据视图。此方案的数据绑定表达式可能类似于以下表达式: 
    DataBinder.Eval(DataView1, "[0].au_lname")
    索引值零 ([0]) 指示表达式将只获取来自由数据视图表示的第一个(只是推测)记录的数据。 只用一个记录填充数据集。但是,这可能不是使用数据集的有效方式。 
    此外,您还可以选择在代码中对该控件进行数据绑定。这样做使您可以编程方式确定要绑定到的数据行,这可能包括执行 SQL 语句或存储过程并绑定到结果。有关详细信息,请参阅在运行时数据绑定单值 Web 服务器控件。绑定模板中的单值控件
    多记录控件(例如 DataList、Repeater 和 DataGrid 控件)包括用来呈现来自数据源的单独记录的模板。而模板又经常包含绑定到数据的单值控件,例如 TextBox 和 Label 控件。 注意 有关模板的详细信息,请参阅 Web 服务器控件模板。
    因为模板中的单值控件可以只绑定到一个值,所以需要指定要绑定到的记录。通过在数据绑定表达式中公开可以使用的两个对象,父控件使以下情况成为可能: Container 对象引用父控件,而该父控件又绑定到一个数据源。 
    DataItem 对象引用当前正由该父控件处理的记录。 
    DataList 控件模板中 TextBox 控件的数据绑定表达式可能类似下面的表达式:DataBinder.Eval(Container, "DataItem.au_lname")
      

  2.   

    Web 窗体页的数据绑定表达式
    对 Web 窗体页中的各项控件属性进行数据绑定不是通过直接将属性绑定到数据源来实现的。而是通过使用特殊的表达式格式来实现数据绑定的。与要绑定到的数据有关的信息被置入该表达式,然后将表达式的结果分配给控件属性。例如,假设您要将 TextBox Web 服务器控件绑定到一些数据。您创建数据绑定表达式并将其分配给控件的 Text 属性,以便该值将在控件中显示。下面的示例说明控件声明在 HTML中的大体形式。控件的 Text 属性被绑定到包含单个记录的数据视图。数据绑定表达式是用字符 <%# 和 %> 分隔的。<asp:TextBox id="TextBox1" runat="server" 
       Text='<%# DataView1(0)("au_lname") %>'>
    </asp:TextBox>
    同样,可以使用数据绑定表达式来设置 Image Web 服务器控件的 ImageUrl 属性。在这种情况下,您是在从数据库中提取一个字符串,该字符串包含要显示的图形的路径和文件名。一个示例可能类似于如下所示:<asp:Image id=Image1 runat="server" 
       ImageUrl='<%# DataView(0)("productPhotoURL") %>'>
    使用数据绑定表达式的优点
    使用数据绑定表达式在以下几个方面为您提供灵活性: 可以使用任何表达式,只要该表达式解析为控件可以使用的值。最常见的是,数据绑定表达式将解析为从数据源导出的值,但它还可以引用该页或其他控件的属性、您在运行时计算出的值或几乎任何其他项。 
    可以将表达式分配给任何属性——也就是说,可以将任何属性绑定到数据。例如,您可以将与用户首选项有关的信息保留在数据库中,并且使用数据绑定为字体、颜色、大小、样式等实现属性中的那些首选项。此外,可以绑定不止一个控件属性,这使您可以将一个属性绑定到一个数据源,将另一个属性绑定到不同的源。 
    使用 DataBinder 类用于绑定
    尽管您可以实际使用解析为一个值的任何表达式来进行数据绑定,但在大多数情况下,您将绑定到某些类型的数据源。最为常见的情况是数据集或数据视图中的表,表中包含您感兴趣的单个记录。为了简化此类型的数据绑定,ASP.NET 服务器控件支持名为 DataBinder 的类,它执行某些提取数据并使其可用于控件属性的工作。可以通过调用其 Eval 方法来使用 DataBinder 类,这要求两个参数: 对数据容器(通常是数据集)、数据表或数据视图的引用。 
    对要被导出的单独的值的引用。这通常引用单行(行零)和该行中的列值。 
    下面的示例说明与上面的文本框所执行的相同的数据绑定,但这一次使用 DataBinder 类。<asp:TextBox id="TextBox1" runat="server" 
       Text='<%# DataBinder.Eval(DataView1, "[0].au_lname") %>'>
    </asp:TextBox>
    先前设置 Image 控件 ImageUrl 属性的示例可能类似于如下所示。在该示例中,一个格式设置表达式在 DataBinder.Eval 方法的第二个参数(可选)中传递;该表达式将一个路径当作前缀添加到数据中。<asp:Image id=Image1 runat="server" 
       ImageUrl='<%# DataBinder.Eval(Container, "DataItem.ProductImage", "http://myserver/myapps/images/{0}") %>'>
    使用 DataBinder 类的优点是: 语法对于所有绑定是一致的,由 Eval 方法所需的参数强制采用的。 
    类自动执行类型转换。例如,如果将一个文本框绑定到包含整数的数据列,DataBinder 类自动将整数转换为字符串。 
    您可以选择指定一个可转换或修正数据的格式设置表达式。 
    解析数据绑定表达式
    为了提供控件可以绑定到的值,必须在运行时解析数据绑定表达式。通过调用 DataBind 方法(它是 System.Web.UI.Control 类的方法),可以在页处理期间显式执行此步骤。可以为单独的控件调用该方法,或者更为有效的是,可以为 Page 类(也是从 Control 类导出的)调用该方法。此方法级联对所有子控件的调用,所以通过为该页调用此方法一次,您可以为该页上的所有控件调用它。通常在以下情况下调用 DataBind 方法: 该页第一次运行时,但在填充数据源之后(例如,在您已填充数据集之后)。 
    在数据源发生更改之后(例如,因为已更新了数据源中的记录)。 
    下面的示例说明在页初始化事件期间调用 DataBind 方法的典型方式:' Visual Basic
    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
       SqlDataAdapter1.Fill(DsAuthors1, "authors")
       If Not (Me.IsPostBack) Then
         Me.DataBind()
       End If
    End Sub// C#
    private void Page_Load(object sender, System.EventArgs e)
    {
       SqlDataAdapter1.Fill(DsAuthors1, "authors");
       if (!this.IsPostBack) 
       {
          this.DataBind();
       }
    }
    通常不需要在每个往返行程中都调用 DataBind 方法(即在页初始化中不需要检查回发),因为这样做会替换控件中的值。例如,如果您使用 DataGrid 控件,该控件可能包含您要处理的更改。在您调用 DataBind 时,用来自数据源的值代替网格的内容。如果在页初始化期间执行此操作,您将在有机会处理更改前,失去网格中的更改。您而是应通常在为该事件执行了数据处理后,在事件处理程序中调用 DataBind 方法。多记录控件(例如 Repeater、DataList、DataGrid、ListBox、CheckBoxList 和 RadioButtonList 控件)被绑定到包含多个数据项的数据源。例如,可以将 DataGrid 控件绑定到数据集中的一个表并且该控件可以直接显示数据。或者可以将 DataList 或 Repeater 控件绑定到数据集中的一个表,并且使该控件可用于子控件。还可以将 HtmlSelect 控件绑定到多个记录。该过程不同于上面列出的用于 Web 服务器控件的过程。有关详细信息,请参阅数据绑定 HTML 服务器控件。注意 此过程讨论将控件绑定到包含多个数据项的对象的设置属性。您还可以使用数据绑定来设置这些控件中单值属性的值。例如,您可以使用单值数据绑定设置该控件的 Width 或 BackColor 属性。有关详细信息,请参阅在设计时数据绑定单值 Web 服务器控件。
    绑定多记录控件 将该控件的 DataSource 属性设置为包含您要绑定到的数据项的对象。 
    容器对象必须实现 IEnumerable 接口,这包括下列对象: ArrayList 对象 
    集合 
    数据阅读器(OleDbDataReader 和 SqlDataReader 类型的对象) 
    DataView 对象 
    DataRow 对象 
    数据集中的 DataTable 对象 
    如果数据源是数据集,将 DataMember 属性设置为要绑定到的表的名称。(如果未设置该属性,默认情况下使用数据集中的第一个表。) 
    如果使用 DataList 或 DataGrid 控件,将 DataKeyField 属性设置为在运行时可使用的列的名称以标识单独的项。如果这是可行的,通常使用数据源的主键列。 
    如果使用 ListBox、DropDownList、CheckBoxList、RadioButtonList 或 HtmlSelect 控件,将 DataTextField 属性设置为要在控件中显示的数据列的名称。 
    可以选择设置 DataValueField 属性来指定在用户选择一项时控件应返回为其值的列的名称。 
    在 Web 窗体页中添加调用控件或页的 DataBind 方法的代码。 
    注意 通常不需要在每个往返行程中都调用 DataBind 方法(即在页初始化阶段不需要检查回发),因为这样做会替换控件中的值。 
    下面的示例说明如何可以数据绑 ListBox 控件。该示例假设您具有名为 DsTitles1 的数据集,并且该数据集包含名为 titles 的表。该表包含两列,一列是标题列,您将其分配给 ListBox 显示文本;另一列是 title_id 列,您将其分配为控件的值。 ' Visual Basic
    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
       SqlDataAdapter1.Fill(DsTitles1)
       If Not (Me.IsPostBack) Then
          ListBox1.DataSource = DsTitles1
          ListBox1.DataMember = "titles"
          ListBox1.DataTextField = "title"
          ListBox1.DataValueField = "title_id"
          ListBox1.DataBind()
       End If
    End Sub// C#
    private void Page_Load(object sender, System.EventArgs e)
    {
       SqlDataAdapter1.Fill(DsTitles1);
       if (! this.IsPostBack) 
       {
          ListBox1.DataSource = DsTitles1;
          ListBox1.DataMember = "titles";
          ListBox1.DataTextField = "title";
          ListBox1.DataValueField = "title_id";
          ListBox1.DataBind();
       }
    }
    下面的示例说明如何将 ListBox 控件绑定到当使用 DataCommand 对象来执行 SQL 语句时所返回的数据。命令对象的 ExecuteReader 方法返回数据阅读器对象(在此情况中,是 SqlDataReader 类型的对象),可以直接将 ListBox 控件绑定到该对象。 ' Visual Basic
    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
       If Not (Me.IsPostBack) Then
          SqlConnection1.Open()
          SqlCommand1.CommandText = "Select au_id, au_lname from authors"
          ListBox1.DataSource = SqlCommand1.ExecuteReader()
          ListBox1.DataTextField = "au_lname"
          ListBox1.DataValueField = "au_id"
          ListBox1.DataBind()
          SqlConnection1.Close()
       End If
    End Sub// C#
    private void Page_Load(object sender, System.EventArgs e)
    {
       if (! this.IsPostBack) 
       {
          SqlConnection1.Open();
          SqlCommand1.CommandText = "Select au_id, au_lname from authors";
          ListBox1.DataSource = SqlCommand1.ExecuteReader();
          ListBox1.DataTextField = "au_lname";
          ListBox1.DataValueField = "au_id";
          ListBox1.DataBind();
          SqlConnection1.Close();
       }