zoukankan      html  css  js  c++  java
  • ADO.NET的数据绑定机制剖析及其应用

        当在程序中需要显示多条记录时,我们往往希望能给记录一个“记录号”以方便定位记录,比如:“到第一条”,“到最后一条”,“跳到第100条”……。

        DataTable中的记录(即DataRow)本身并没有一个所谓的“记录号”,DataTable本身也没有提供这种功能。

        提示:

        在VB6中,记录集对象RecordSet提供MoveFirst,MoveLast等定位功能。这是由ADO实现的。在ADO.NET中,DataTable和DataRow都没有这些方法。

     

        乍看起来,不能在数据集中移动,好象是ADO.NET设计的一个疏漏。事实上,ADO.NET把所有在数据集中定位的功能全部抽取出来,再加上其他一些功能,构建了ADO.NET的数据绑定机制,与原来ADO所提供的有限定位功能相比,ADO.NET更为强大而灵活。

        请试着运行本书配套光盘中的示例MoveInDataTable,其运行界面如715



    715
    数据绑定示例

     

        这个程序在运行时,既可以点击右下方的四个按钮,也可以直接点击上部的网格在数据集中移动,当前行的内容同步在下半部的两个文本框中显示。可以在文本框中直接修改数据,当移动到其它行时,网格中的记录同步刷新。

        通过这个示例,我们来剖析ADO.NET中数据绑定机制的原理。

    1 什么叫数据绑定?

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

     


    716
    数据绑定原理

     

        Windows 窗体可以利用两种类型的数据绑定:简单绑定和复杂绑定。这两种类型具有不同的优点。

    l         简单绑定

        简单数据绑定指将一个控件绑定到单个数据元素(如数据集表的列中的值)的能力。这是用于 TextBox 控件或 Label 控件等控件(即通常只显示单个值的控件)的典型绑定类型。 715中的两个文本框,分别绑定到了DataTable中的“AddressStr”和“ClientName”两个字段。

    l         复杂绑定

        复杂数据绑定指将一个控件绑定到多个数据元素的能力,通常绑定到数据库中的多条记录。 715中的DataGrid就绑定到了一个DataTable,它可以一次显示多条记录和多个字段的值。

     

    2 实现在数据集中移动

        在数据集中移动是数据绑定机制中的一个子功能。

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

     


    717
    手动实现在记录集中移动

    下面对代码进行分析

    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

        在示例程序的第二窗体(参见715)中,只不过是多了将文本框绑定到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绑定。

        文本框绑定的第三个参数被称为“绑定字串”,以英文句点隔开,其格式为:

             表名.字段名

        其特点是越左边的子字串其范围就越大。

     

    技术内幕:

         其实数据绑定不仅限于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的数据绑定机制主要由以下类构成:

     


    718
    数据绑定类

     

        718以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))

     

     

    自我探索:

        一个容器控件比如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

     

    是不是非常简单?

    从这个小示例中相信您一定能体会到面向对象技术所带来的好处!
    原文出自:http://blog.csdn.net/bitfan/archive/2005/02/02/278461.aspx

  • 相关阅读:
    LevelDB的源码阅读(二) Open操作
    LevelDB的源码阅读(一)
    Linux上leveldb的安装和使用
    Linux下安装jdk8的详细步骤
    Linux下用ls和du命令查看文件以及文件夹大小
    pytorch实现VAE
    Caffe实现VAE
    pytorch实现DCGAN、pix2pix、DiscoGAN、CycleGAN、BEGAN以及VAE
    PyTorch教程之Training a classifier
    PyTorch教程之Neural Networks
  • 原文地址:https://www.cnblogs.com/xiaolin/p/586875.html
Copyright © 2011-2022 走看看