您的位置:首页 > 其它

ADO.NET的数据绑定机制剖析及其应用

2007-12-28 09:46 357 查看

这是我写的书的一部分,全部原创,刚完成,欢迎提出意见。

                                       bitfan

 -------------------------------------------------------

                           

7.5.2 在数据集中移动

    当在程序中需要显示多条记录时,我们往往希望能给记录一个“记录号”以方便定位记录,比如:“到第一条”,“到最后一条”,“跳到第100条”……。    DataTable中的记录(即DataRow)本身并没有一个所谓的“记录号”,DataTable本身也没有提供这种功能。    提示:[/b]    在VB6中,记录集对象RecordSet提供MoveFirst,MoveLast等定位功能。这是由ADO实现的。在ADO.NET中,DataTable和DataRow都没有这些方法。     乍看起来,不能在数据集中移动,好象是ADO.NET设计的一个疏漏。事实上,ADO.NET把所有在数据集中定位的功能全部抽取出来,再加上其他一些功能,构建了ADO.NET的数据绑定机制,与原来ADO所提供的有限定位功能相比,ADO.NET更为强大而灵活。    请试着运行本书配套光盘中的示例MoveInDataTable,其运行界面如图 7 15:




图 7 15 数据绑定示例     这个程序在运行时,既可以点击右下方的四个按钮,也可以直接点击上部的网格在数据集中移动,当前行的内容同步在下半部的两个文本框中显示。可以在文本框中直接修改数据,当移动到其它行时,网格中的记录同步刷新。    通过这个示例,我们来剖析ADO.NET中数据绑定机制的原理。

1 什么叫数据绑定?

    所谓数据绑定,通俗地说,就是把数据源(如DataTable)中的数据取出来,显示在窗体的各种控件上,用户可以通过这些控件查看和修改数据,这些修改会自动地保存到数据源中,参见图 7 16。 


图 7 16 数据绑定原理     Windows 窗体可以利用两种类型的数据绑定:简单绑定和复杂绑定。这两种类型具有不同的优点。 l         简单绑定    简单数据绑定指将一个控件绑定到单个数据元素(如数据集表的列中的值)的能力。这是用于 TextBox 控件或 Label 控件等控件(即通常只显示单个值的控件)的典型绑定类型。 图 7 15中的两个文本框,分别绑定到了DataTable中的“AddressStr”和“ClientName”两个字段。l         复杂绑定    复杂数据绑定指将一个控件绑定到多个数据元素的能力,通常绑定到数据库中的多条记录。 图 7 15中的DataGrid就绑定到了一个DataTable,它可以一次显示多条记录和多个字段的值。 

2 实现在数据集中移动

    在数据集中移动是数据绑定机制中的一个子功能。    为了方便理解ADO.NET中复杂的数据绑定机制,我们先在MoveInDataTable示例中的一个简单的窗体内实现数据移动功能,参见图 7 17: 


图 7 17 手动实现在记录集中移动下面对代码进行分析(1)程序需要提取数据,Sub过程GetData实现这一功能:    '定义相关变量    Private conn As OleDbConnection    Private comm As OleDbCommand    Private da As OleDbDataAdapter    Private ds1 As New DataSet         '获取数据    Private Sub GetData()        '创建连接对象连接数据库        conn = New OleDbConnection        conn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:/Clients.mdb;Persist Security Info=False"        conn.Open()        '创建命令对象用于向数据库发送SQL命令        comm = New OleDbCommand        comm.CommandText = "select * from OrderClient"        comm.CommandType = CommandType.Text        comm.Connection = conn        '创建DataAdapter用于填充DataSet        da = New OleDbDataAdapter(comm)        '填充数据        da.Fill(ds1)        conn.Close()    End Sub 注意,假设数据库Clients.MDB放在“D:/”下。这些代码我们已经很熟悉了。(2)设定数据绑定,Sub过程SetDataBing()实现这一功能:       '数据绑定管理对象    Private cm As CurrencyManager     '设置数据绑定    Private Sub SetDataBinding()        '将DataGrid绑定到DataTable        Me.DataGrid1.DataSource = ds1.Tables(0)        '获取数据绑定管理对象        cm = Me.BindingContext(ds1.Tables(0))    End Sub    在示例程序的第二窗体(参见图 7 15)中,只不过是多了将文本框绑定到DataTable中的字段中的代码:        Me.txtAddress.DataBindings.Add("Text", ds1.Tables(0), "AddressStr")        Me.txtName.DataBindings.Add("Text", ds1.Tables(0), "ClientName")    可以看到,给DataGrid设置数据绑定非常简单,只需直接设定其DataSource属性就行了。    给文本框设置数据绑定,需要向其DataBindings集合增加一项,其格式为:         "要绑定的属性名", 被绑定的DataTable对象, "DataTable中的字段名"    在上面的代码中,控件都是直接绑定到DataTable中的,事实上,也可直接绑定到DataSet,但这时需要对代码做一些改变:         '将DataGrid绑定到DataTable        Me.DataGrid1.DataSource = ds1        Me.DataGrid1.DataMember = ds1.Tables(0).TableName        '绑定文本框         Me.txtAddress.DataBindings.Add("Text", ds1, ds1.Tables(0).TableName & ".AddressStr")        Me.txtName.DataBindings.Add("Text", ds1, ds1.Tables(0).TableName & ".ClientName")     因为DataSet中可能会有多个DataTable,所以,必须给DataGrid的DataMember属性指明一个表名。在程序中动态指定某个DataTable表名,就可以动态地将DataGrid与此表名相对应的DataTable绑定。    文本框绑定的第三个参数被称为“绑定字串”,以英文句点隔开,其格式为:         表名.字段名    其特点是越左边的子字串其范围就越大。 技术内幕:[/b]     其实数据绑定不仅限于DataSet和DataTable,同样可以将文本框和DataGrid之类绑定到其它对象,如数组和ArrayList,这时,绑定字串就显得非常重要了,有兴趣的读者可以在MSDN中通过搜索“数据绑定”关键字了解如何绑定到非DataSet和DataTable数据。 (3)现在可以在记录集中移动了,这是通过给CurrencyManager的Position属性赋值实现的,下面列出了关键的代码:      '移到第一条     cm.Position = 0     '移到前一条     If cm.Position > 0 Then            cm.Position -= 1     End If        '移到下一条     If cm.Position < cm.Count - 1 Then            cm.Position += 1     End If     '移到最后一条    cm.Position = cm.Count - 1     可以看到,在数据集中移动是通过CurrencyManager对象来实现的。     展示的代码虽然简单,但如果不理解这背后所隐藏的机制,还是无法充分地利用数据绑定机制的。

3 数据绑定原理

ADO.NET的数据绑定机制主要由以下类构成: 


图 7 18 数据绑定类     图 7 18以UML图符方式展示了ADO.NET中数据绑定的核心架构(注意,并没有完整地画出所有的类)。 提示:    UML简称为Unified Modeling Language(统一建模语言),它使用图形的方式来表达面向对象的软件系统架构,目前已被软件业广泛接受,成为了国际标准。本书第四部分介绍面向对象编程中就大量地使用UML类图表达程序结构。本书附录中有一个UML基础教程,可供读者参考学习。    现在逐个介绍每个类。    从示例中我们已经知道,象文本框这样的控件都可以绑定到字段上,这一事实本身包含以下信息:    要绑定的自身属性(如Text属性)    提供数据来源的对象(如DataTable)    绑定导航字串    …………    这些信息被封装起来,形成了Binding类。每个实现了数据绑定的控件都至少有一个Binding对象,表明它的绑定信息。    一个窗体上可能会有多个控件(比如多个文本框)绑定到一个数据源,这就意味着存在着多个Binding对象。因此需要有一个类来管理这些对象,这个类就是BindingManagerBase类,但这个类是个抽象类,不能直接创建对象,类CurrencyManager直接继承自BindingManagerBase类,实现了所有基类未实现的功能,可以直接被使用。在数据集中移动的功能就是由 CurrencyManager对象实现的。    现在知道了,要在数据集中移动,必须想法获取与此数据集对应的CurrencyManager对象。那怎样做到这点?    一个窗体上不仅会有多个控件(比如多个文本框)绑定到一个数据源,还可能出现多个控件绑定到多个数据源的情况(假设窗体中有两个DataSet,分别为两组控件提供数据,则在窗体中就会存在两个CurrencyManager对象),因此,再设计一个类用于管理这些CurrencyManager对象,这就是BindingContext类的功能。每个其上有数据绑定的窗体对象都至少会有一个BindingContext对象。    现在小结一下:    获取窗体的BindingContext对象à由BindingContext对象获取CurrencyManager对象à通过CurrencyManager对象以实现在记录集中移动的功能    这就是实现在数据集中移动功能的技术内幕。    说了这么多,其实在示例代码中只需要一句就行了:'数据绑定管理对象         Private cm As CurrencyManager         '…………        '获取数据绑定管理对象        cm = Me.BindingContext(ds1.Tables(0))   自我探索:[/b]    一个容器控件比如Form、GroupBox和TabControl都可以有自己的BindingContext对象,以下代码设定了两个GroupBox的BindingContext对象:    Dim bcG1 As New BindingContext()    Dim bcG2 As New BindingContext()           groupBox1.BindingContext = bcG1    groupBox2.BindingContext = bcG2    请设计一个应用程序,其上有两个GroupBox,每个GroupBox中都有一些数据绑定控件,编程实现这两组控件显示同一数据源中的不同位置的数据。

3 设计数据绑定辅助类

    从前面介绍的内容可以看到,ADO.NET提供的数据绑定功能虽然灵活,但确实过于复杂而不好用了,而在数据集中移动的功能是非常常见的,如果在每一个窗体中都重复这些代码,实在是一件枯燥无聊的工作。因此,可以把这些代码封装起来,作为一个数据绑定辅助类。DataBindingHelper类就是出于这个目的而创建的。    首先定义一些类的成员变量: '内部绑定管理器    Private _cm As CurrencyManager = Nothing    '内部的绑定控件容器,通常是窗体    Private _container As Control = Nothing     '向外界表露CurrencyManager对象    Public ReadOnly Property cm() As CurrencyManager        Get            Return _cm        End Get    End Property     '容器控件    Public Property container() As Control        Get            Return _container        End Get        Set(ByVal Value As Control)            _container = Value        End Set    End Property 接着需要提供一个方法来指定数据源: '数据源属性,可以指定DataMember(对于DataSet),也可省略,对于DataTable    Public Sub setDataSource(ByVal datasource As Object, Optional ByVal dataMember As String = Nothing)         If _container Is Nothing Then            MsgBox("请先指定控件容器")            Exit Sub        End If        If dataMember Is Nothing Then            _cm = _container.BindingContext(datasource)        Else            _cm = _container.BindingContext(datasource, dataMember)        End If    End Sub 现在就可以实现移动功能了,以后移一条记录为例:      Public Sub MoveNext()        '_cm未创建或为空,均退出        If _cm Is Nothing Then            Exit Sub        End If        If _cm.Count = 0 Then            Exit Sub        End If         If _cm.Position < _cm.Count - 1 Then            _cm.Position += 1        End If    End Sub 有了DataBindingHelper类,实现在数据集中移动就非常简单了,以下是示例工程中的代码: Dim dbh1 As New DataBindingHelper'设定容器对象为窗体        dbh1.container = Me‘设定数据源        dbh1.setDataSource(ds1.Tables(0))移动代码如下:Private Sub btnMoveFirst1_Click(……) Handles btnMoveFirst1.Click        dbh1.MoveFirst()    End Sub     Private Sub btnMovePrev_Click(……) Handles btnMovePrev.Click        dbh1.MovePrev()    End Sub 是不是非常简单?从这个小示例中相信您一定能体会到面向对象技术所带来的好处!

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=278461
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: