摘要: DataGrid 控件是与 ASP.Net Page Framework 一起发行的数据绑定的服务器控件。本文使用 DataGrid 来建立包含动态表格视图的 Web 页面。还探讨控件所提供功能的各个方面,包括选择、删除、分页和模板列 ,而控件就是使用这些功能来建立最终的页面的。
简介
DataGrid 控件可以用于若干个只读数据。该控件可用于数据表格布局的输出进行简化。还提供多个机制,用于通过超级链接及其对选择、排序、分页和原地编辑和其它特性的支持,为输出添加交互性。这使得该控件在若干的常见 Web 应用方案中很有用,诸如列表、购物车和查询结果。
DataGrid 还提供一些功能,这些功能具有 ASP.NET 架构所特有的所有服务器控件的特点。该控件包含进行与浏览器无关的输出所需的逻辑,同时提供了一个统一的编程模型,从而能够处理回传数据,以及对请求之间的状态进行管理。这样,开发者就可以针对带有属性、方法和事件的对象模型进行编程,而不必处理直接用 HTML编程所带来的不一致性和复杂性。
我们要建立什么?
本文举出了一系列的示例页面,彼此结合,从而最终生成一个页面,该页面以示例数据库的 Authors 表和 Titles 表为依据,提供主/详细资料视图(该数据库随 Microsoft SQL Server?2000 一起发运)。序列中的每个页面均介绍 DataGrid 控件的一个新的特性或功能。下图从 pubs 数据库抽取出来的。 主/详细资料视图似于 Microsoft Access 所介绍的窗体/子窗体概念。也类似于随 Microsoft Visual InterDev 6.0 一起发表的 DataForm Wizard (数据窗体向导)。主/详细资料视图显示一到多的关系结果,其中视图的一个部分显示第一个查询或主查询的结果。然后跟踪一个选择,以筛选所使用的第二个查询的结果,从而在视图的另一部分显示选择内容的详细资料。
图 1 将 Author 列表显示在页面的上半部分,并将关于所选作者的详细资料(包括相关书名)显示在下半部分。 Authors 列表和 Titles 均是用 DataGrid 控件加以表示的。 显示作者的 DataGrid 举例说明如何进行选择、排序、和分页。显示书名的 DataGrid 演示如何进行原地编辑、格式化和定制列。
数据访问
为了使示例自成一体,从 SQL Server 抽取数据并将该数据连同其架构信息一同保留为一个 XML 文件 TitlesDB.xml。下面是该文件的一个片断。
<root> <schema id="DocumentElement" targetNamespace="" xmlns="http://www.w3.org/1999/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <element name="Author"> <complexType content="elementOnly"> <element name="au_id" type="string" minOccurs="1" maxOccurs="1"></element> <element name="au_name" type="string" minOccurs="1" maxOccurs="1"></element> <element name="address" type="string" minOccurs="0" maxOccurs="1"></element> <element name="city" type="string" minOccurs="0" maxOccurs="1"></element> <element name="state" type="string" minOccurs="0" maxOccurs="1"></element> <element name="zip" type="string" minOccurs="0" maxOccurs="1"></element> <element name="phone" type="string" minOccurs="0" maxOccurs="1"></element> </complexType> <unique name="AuthorConstraint" msdata:PrimaryKey="True"> <selector>.</selector> <field>au_id</field> </unique> </element>
<element name="Title"> <complexType content="elementOnly"> <element name="title_id" type="string" minOccurs="1" maxOccurs="1"></element> <element name="au_id" type="string" minOccurs="1" maxOccurs="1"></element> <element name="title" type="string" minOccurs="1" maxOccurs="1"></element> <element name="price" msdata:DataType="System.Currency" type="string" minOccurs="1" maxOccurs="1"></element> <element name="pubdate" type="timeInstant" minOccurs="1" maxOccurs="1"></element> </complexType> <unique name="TitleConstraint" msdata:PrimaryKey="True"> <selector>.</selector> <field>title_id</field> </unique> <key name="AuthorTitle"> <selector>../Author</selector> <field>au_id</field> </key> <keyref refer="AuthorTitle"> <selector>.</selector> <field>au_id</field> </keyref> </element> </schema> <DocumentElement> <Author> <au_id>154-00-1300</au_id> <au_name>John Doe</au_name> <phone>425 705 1234</phone> <address>One Microsoft Way</address> <city>Redmond</city> <state>CA</state> <zip>98005</zip> </Author>
<Title> <title_id>BU1032</title_id> <au_id>213-46-8915</au_id> <title>The Busy Executive's Database Guide</title> <price>19.99</price> <pubdate>1991-06-12T07:00:00</pubdate> </Title> </DocumentElement> </root>
|
这些样例简化了数据访问,从而将重点全部放在 DataGrid 的使用上。上面的 XML 被加载进一个 DataSet。 DataSet 为数据提供高速缓存,从而可以进行筛选、排序和编辑等等各种操作。下面的代码来自 Global.asax,用于加载 DataSet 和将其保存为 Session 状态。
public void Session_OnStart() { // 将样例中所用的数据载入会话范围的 DataSet.
FileStream fs = null; DataSet ds = null; try { fs = new FileStream(Server.MapPath("Data\\TitlesDB.xml"), FileMode.Open, FileAccess.Read); ds = new DataSet(); ds.ReadXml(fs); } finally { if (fs != null) { fs.Close(); fs = null; } } Session["AppData"] = ds; } |
在实际的 Web 应用程序中,通常不是使用处于 Session 或 Application 状态的高速缓存数据,而是通过所存储的过程、中间层业务对象,或通过调用 Web 服务所揭示的方法来访问和修改数据。无论采取怎样的手段来访问数据,您会发现你依旧以同样的方式来编程和与控件的对象模型进行进行交互。
第 1 步: 一个基本的 DataGrid
序列的第一步展示了一个页面,其中包含单独一个 DataGrid 控件,用于显示来自数据源的一个只读图书列表。
图 2. 完成第 1 步后的页面
DataGrid 声明来自:
<%@ Register TagPrefix="cr" Namespace="CrystalDecisions.Web" Assembly="CrystalDecisions.Web" %> <%@ Page Language="vb" AutoEventWireup="false" Codebehind="Borrow.aspx.vb" Inherits="borrrow.Borrow"%> <%@ Register TagPrefix="cr" Namespace="CrystalDecisions.Web" Assembly="CrystalDecisions.Web" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <title>档案、图书流通管理</title> <meta content="Microsoft Visual Studio.NET 7.0" name="GENERATOR"> <meta content="Visual Basic 7.0" name="CODE_LANGUAGE"> <meta content="JavaScript" name="vs_defaultClientScript"> <meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema"> </HEAD> <body bgColor="beige" MS_POSITIONING="GridLayout"> <form id="Form1" method="post" runat="server"> <asp:label id="Label14" style="Z-INDEX: 101; LEFT: 100px; POSITION: absolute; TOP: -50px" runat="server" Width="47px" Height="18px"></asp:label> <asp:linkbutton id="LinkFind" style="Z-INDEX: 105; LEFT: 361px; POSITION: absolute; TOP: 182px" runat="server" Width="33px" Height="22px" ToolTip="按此进行查询" ForeColor="#0000C0">查询</asp:linkbutton> <TABLE style="Z-INDEX: 104; LEFT: 133px; WIDTH: 637px; POSITION: absolute; TOP: 75px; HEIGHT: 74px" cellSpacing="1" cellPadding="1" width="637" border="1"> <TR> <TD style="WIDTH: 92px"> <asp:label id="lblFind1" runat="server" ForeColor="Green">检索号</asp:label> </TD> <TD style="WIDTH: 196px"> <asp:textbox id="txtFind1" runat="server" Width="199px" Height="26px"></asp:textbox> </TD> <TD style="WIDTH: 83px"> <asp:label id="lblFind4" runat="server" ForeColor="Green">标准号</asp:label> </TD> <TD> <asp:textbox id="txtFind4" runat="server" Width="243px" Height="26px"></asp:textbox> </TD> </TR> <TR> <TD style="WIDTH: 92px"> <asp:label id="lblFind2" runat="server" ForeColor="Green">标准书号</asp:label> </TD> <TD style="WIDTH: 196px"> <asp:textbox id="txtFind2" runat="server" Width="199px" Height="26px"></asp:textbox> </TD> <TD style="WIDTH: 83px"> <asp:label id="lblFind5" runat="server" ForeColor="Green">分类号</asp:label> </TD> <TD> <asp:textbox id="txtFind5" runat="server" Width="243px" Height="26px"></asp:textbox> </TD> </TR> <TR> <TD style="WIDTH: 92px"> <asp:label id="lblFind3" runat="server" ForeColor="Green">图书名称</asp:label> </TD> <TD style="WIDTH: 196px"> <asp:textbox id="txtFind3" runat="server" Width="199px" Height="26px"></asp:textbox> </TD> <TD style="WIDTH: 83px"> <asp:label id="lblFind6" runat="server" ForeColor="Green">检索号</asp:label> </TD> <TD> <asp:textbox id="txtFind6" runat="server" Width="242px" Height="26px"></asp:textbox> </TD> </TR> </TABLE> <asp:datagrid id="DataGrid1" style="Z-INDEX: 102; LEFT: 129px; POSITION: absolute; TOP: 213px" runat="server" Width="1600px" Height="325px" AlternatingItemStyle-Wrap="False" CellPadding="4" BorderWidth="1px" BorderStyle="None" BorderColor="#CC9966" BackColor="White" AllowPaging="True" ToolTip="可按选择按钮选择所要借阅的图书、资料"> <FooterStyle Wrap="False" ForeColor="#330099" BackColor="#FFFFCC"></FooterStyle> <HeaderStyle Font-Bold="True" Wrap="False" HorizontalAlign="Left" ForeColor="#FFFFCC" BackColor="#990000"></HeaderStyle> <PagerStyle HorizontalAlign="Center" ForeColor="#330099" BackColor="#FFFFCC" Wrap="False" Mode="NumericPages"></PagerStyle> <SelectedItemStyle Font-Bold="True" Wrap="False" ForeColor="#9900FF" BackColor="#FFCC66"></SelectedItemStyle> <EditItemStyle Wrap="False"></EditItemStyle> <AlternatingItemStyle Wrap="False"></AlternatingItemStyle> <ItemStyle Wrap="False" ForeColor="#CC9900" BackColor="White"></ItemStyle> <Columns> <asp:ButtonColumn Text="查阅" HeaderText="选择" CommandName="Select" ItemStyle-ForeColor="#3366CC"></asp:ButtonColumn> </Columns> </asp:datagrid> <asp:LinkButton id="LinkSumit" style="Z-INDEX: 109; LEFT: 816px; POSITION: absolute; TOP: 184px" runat="server" Width="42px" Height="18px" ToolTip="可按此把借阅信息传入管理人员" ForeColor="#0000C0">提交</asp:LinkButton> <asp:Label id="Label1" style="Z-INDEX: 110; LEFT: 138px; POSITION: absolute; TOP: 186px" runat="server" ForeColor="#C00000">你已经选择了该行!</asp:Label> </form> </body> </HTML>
|
上面的代码展示 DataGrid,该控件的各种属性已经过声明设定。 DataGrid 控件与其它 Web 控件如 Font、BackColor、ForeColor 和 BorderWidth 共享一组公用的样式属性。另外, DataGrid 提供仅适用于表的属性如 CellPadding。最后, DataGrid 提供附加的样式属性,这些样式属性影响其中各项目和列如 HeaderStyle、ItemStyle 和 AlternatingItemStyle 的表示。这些样式属性用于创建丰富多采且极富魅力的数据视觉效果。
DataGrid 支持从其所绑定的数据源自动生成列的功能。在本例中, AutoGenerateColumns 属性已被设定为 true。因此必须借助要展示的列集对 Columns 集合进行绑定。从而可以更多地控制表现效果,诸如列的次序和标头以及与每列对应的样式。这一步中所定义的列均为 BoundColumns,从而可以通过其 DataField 属性,绑定到数据源的单独一个字段。您在以后步骤中可以看到, DataGrid 允许选择各种各样类型的列。
下面的类包含支持本页面的代码。
Step1Page.vb:
Imports System.DBNull Imports System.Data Imports System.Data.SqlClient Imports System.Data.OleDb Imports System.DateTime Imports DataAccess
Public Class Borrow Inherits System.Web.UI.Page Public DB As New OleDataAccess() Dim myDataSet As New DataSet()
Dim SelectTable As New DataTable() Dim SelectView As New DataView() … Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim info As String, time If Not Page.IsPostBack Then If Now.Hour >= 6 And Now.Hour < 12 Then info = "早上好!!" ElseIf Now.Hour > 12 And Now.Hour < 18 Then info = "下午好!!" Else info = "晚上好!!" End If Dim Counter As Int16 Counter = Application("Counter") lblInfo.Text = Application("UserName") + "," + info + Chr(13) + "欢迎你前来借阅 。." + Chr(10) + "你是第" + Counter.ToString + "位来访者!"
End If If IsNothing(Session("mTable")) Then SelectTable = CreateTable() Session("mTable") = SelectTable SetText() Else SelectTable = Session("mTable") End If End Sub Private Function CreateTable() As DataTable Dim dt As New DataTable() Dim dr As DataRow dt.Columns.Add(New DataColumn("ID", GetType(String))) dt.Columns.Add(New DataColumn("Name", GetType(String))) ' dt.Columns(0).ColumnName = "系号" ' dt.Columns(1).ColumnName = "名称" Return dt End Function End Class
|
该类超越 Page 的 OnLoad 方法 (类似于实施 Page_Load),将 建立一个临时表并巧妙地利用Session在加载页面时保证仅执行一次。与其它一般页面一样,确定来访者人数。
第 2 步: 带有动态绑定的DataGrid
创建带有动态绑定的DataGrid视图的一个方法就是一个DataGrid来显示不同的数据表格的内容。这里有个必须解决的问题,就是不同的表在一个表格中怎样绑定?如何确定表的字段,特别是表的英文字段怎样变成中文?大多数的方法是用绑定字段方法实现,在绑定字段后改变标题,这种方法是不可取的。一般不能实现动态绑定,因在绑定字段时必须先申明DataGrid,这里,我们是不允许申明二个以上的DataGrid。正确的方法是在用表绑定DataGrid前临时改变表的字段名。下面就是实现的方法
页包含对DataGrid 的数据绑定。DataGrid 用于显示图书和档案的内容。与第 1 步相同, DataGrid 包含一个针对要显示的列的定义,以及用于为列、行和总体控制提供可视格式化的样式属性设置。在绑定之前先根据用户的选择进行查询。查询内容是不变化的,我们通过SetText过程来动态设置标题。在查询前先生成查询语句,通过查询语句改变其字段名,同时进行动态的模糊查询。这里要说明的是页面是不能保留数据的,所以我们用到了应用对象Application来保留数据。
Step2aPage.vb 包含支持详细资料页面的代码。
Step2aPage.vb:
Imports System.DBNull Imports System.Data Imports System.Data.SqlClient Imports System.Data.OleDb Imports System.DateTime Imports DataAccess
Public Class Borrow Inherits System.Web.UI.Page Public DB As New OleDataAccess() Dim myDataSet As New DataSet() Dim SelectTable As New DataTable() Dim SelectView As New DataView() … Private Sub SetText() Select Case Application("Index") Case 0 lblFind1.Text = "检索号 " lblFind2.Text = "图书分类" lblFind3.Text = "图书名称" lblFind4.Text = "分类号" lblFind5.Text = "作者" lblFind6.Text = "有效性" Case 1 lblFind1.Text = "编号 " lblFind2.Text = "卷册名称" lblFind3.Text = "设计专业代码" lblFind4.Text = "专业代码" lblFind5.Text = "馆藏号" lblFind6.Text = "负责人 " Case 2 End Select End Sub
Private Sub Data2bind() DataGrid2.DataSource = SelectTable.DefaultView DataGrid2.DataBind() End Sub
Private Sub LinkButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LinkButton1.Click Application("Index") = 0 SetText() End Sub
Private Sub LinkButton2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LinkButton2.Click Application("Index") = 1 SetText() End Sub
Private Sub LinkFind_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LinkFind.Click Dim strSql As String Dim txt(6) As String Dim i As Int16 = 0 txt(0) = Trim(txtFind1.Text) txt(1) = Trim(txtFind2.Text) txt(2) = Trim(txtFind3.Text) txt(3) = Trim(txtFind4.Text) txt(4) = Trim(txtFind5.Text) txt(5) = Trim(txtFind6.Text) If txt(0) = "" And txt(1) = "" And txt(2) = "" And txt(3) = "" And txt(4) = "" And txt(5) = "" Then Exit Sub End If For i = 0 To 5 If txt(i) = "" Then txt(i) = "!!!!" Next Try If Application("Index") = 0 Then strSql = "SELECT JSH AS 检索号, TSMC AS 图书名称, TSFL AS 图书分类, CS AS 册数, FLH AS 分类号, DJ AS 单价, ZZ AS 作者, BZ AS 备注, ZBBM AS 主编部门, FBRQ AS 发布日期, SSRQ AS 实施日期, YXX AS 有效性, ZT AS 状态 FROM G2272.KPK " & _ " WHERE JSH LIKE '%" & txt(0) & _ "%' OR TSFL LIKE '%" & txt(1) & _ "%' OR TSMC LIKE '%" & txt(2) & _ "%' OR FLH LIKE '%" & txt(3) & _ "%' OR ZZ LIKE '%" & txt(4) & _ "%' OR YXX LIKE '%" & txt(5) & "%'" Else strSql = "SELECT SYSTEM_ID AS 编号, JCMC AS 卷册名称, GCDM AS 工程代码, ZYDM AS 专业代码, GCH AS 馆藏号, RKRQ AS 入库日期, TZZS AS 图纸张数, GDZB AS 归档正本, GDFB AS 归档副本, JC AS 说明书, ZSR AS 清册, ZBR AS 负责人 FROM DOCSADM.TWML " & _ " WHERE SYSTEM_ID LIKE '%" & txt(0) & _ "%' OR JCMC LIKE '%" & txt(1) & _ "%' OR GCDM LIKE '%" & txt(2) & _ "%' OR ZYDM LIKE '%" & txt(3) & _ "%' OR GCH LIKE '%" & txt(4) & _ "%' OR ZBR LIKE '%" & txt(5) & "%'" End If myDataSet = Application("DB").ExecuteSQL(strSql) DataGrid1.DataSource = myDataSet.Tables(0).DefaultView DataGrid1.DataBind() Catch ex As Exception ' MsgBox("错误信息", ex.Message & vbCrLf & "stack step") End Try End Sub End Class |
3 步: 选择
我们通过动态查询得到所需数据后,然后对其数据操作,这里实现读者借书的功能。
Private Sub DataGrid1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DataGrid1.SelectedIndexChanged Dim dv As DataView = SelectTable.DefaultView() Dim dr As DataRow = SelectTable.NewRow() Dim ID, index As String Dim Name As String Label1.Visible = False index = DataGrid1.SelectedIndex() ID = DataGrid1.Items(index).Cells(1).Text dv.RowFilter = "ID='" + ID + "'" If dv.Count > 0 Then ' Response.Write(". 你已经选择了该行!") Label1.Visible = True Exit Sub End If dv.RowFilter = "" Name = DataGrid1.Items(index).Cells(2).Text dr(0) = ID dr(1) = Name SelectTable.Rows.Add(dr) Data2bind() End Sub |
向列集添加了一个新的列类型 ButtonColumn。该列在每行中生成 LinkButton,用于选择该行,而不是从该页进行浏览。列的 Command 属性设定为 Select。DataGrid 将 Select 作为一个标准命令,将包含被单击按钮的列选定。当用户选择该行时,先取得该行的值,如果该行已选择则提示信息,我们用过虑条件实现,所选择的行插入一临时表,且在另一DataGrid中显示。注意过虑之后应该设置过虑为空,否则得不到结果。
第 4 步: 删除
DataGrid 控件支持标准的列集,它提供一些基础的操作。诸如 BoundColumn、 ButtonColumn 和 TemplateColumn。我们利用ButtonColumn列实现删除功能。
… Private Sub DataGrid2_DeleteCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) Handles DataGrid2.DeleteCommand Dim dv As DataView = SelectTable.DefaultView() Dim ID As String ID = e.Item.Cells(1).Text dv.RowFilter = "ID='" + ID + "'" If dv.Count > 0 Then dv.Delete(0) dv.RowFilter = "" Data2bind() End Sub |
第 5 步: 分页
设置DataGrid的分页方法有二种,一种是数字分页人,另一种是上下分页。实现方法是在属性栏中设置AutoPaging为true,在其属性生成器中设置分页类型。
结论
DataGrid 控件简化了多个常见 Web 应用情形,其中包括只读报表到交互式应用程序 UI。该控件优于传统的 ASP 编程。它将转换对象模型操作和数据绑定所需的逻辑封装进与浏览器无关的 HTML 表现功能。还将处理回传数据以及转换客户机事件的详细资料封状进服务器事件。 该控件设计用于无须作出太多开发努力就可以表现您的数据。随着应用要求的改变,以及您开始使用 DataGrid 的各种功能,您可以逐步添加其它功能。
|