分享

True DBGrid

 ufo999 2010-01-08
蒋匪软件窝->技术资料->网络编程----本文转载自网管联盟

 

True DBGrid提供了空前灵活的数据源选择,你可以直接绑定到 Visual Basic的内部数据控件、 OLE DB数据源(例如: Microsoft's ADO Data Control and Remote Data Services (RDS))、或者一个第三方数据控件(例如: APEX's True DBWizard)。在绑定模式使用 True DBGrid常常简化数据库的开发,让你能集中精神在你的应用程序界面开发上,避免了数据访问的细节。

然而,很多时候绑定到一个数据控件即不实用也不合要求。这时就需要非绑定模式下的操作。数据控件会增加开销,在大数据结果集的情况下会导致性能下降。即使是你仅需要需要在一个网格里显示一个简单的两维阵列,为什么要调入整个数据库呢?

如果你使用一个支持多行指令的数据库 API工作,应该使用基于行的非绑定模式。虽然非绑定模式是最难实现的数据访问方式,但它比应用程序模式更有效,因为需要触发的事件更少。如果新开发一个程序,应使用模式 2

TDBG支持基于行的非绑定模式,该模式不依靠 Data控件,与之相应的是,只要网格需要要接收一组相邻行或升级、添加或删除个别行,都会触发非绑定模式的事件。一个中间列缓冲对象服务作为网格和数据源之间的桥梁。

两个非绑定模式:模式 1 ―― Unbound;模式 2―― Unbound Extended,有些不同的事件语法,能简化代码,使这更加有效。

在设计的时候,设置网格的 DataMode 属性为 2- Unbound Extended,在代码里,为 UnboundReadDataEx写一个处理过程,如果你的用户需要添加、修改和删除记录,你则需要为 UnboundAddData, UnboundWriteData, 和 UnboundDeleteRow事件写处理过程

不管你是否使用模式 1 或模式 2,所有网格的 bookmarks相关属性、方法和事件 (Bookmark, FirstRow, GetBookmark, FetchCellStyle, 及其他 )在基于行的非绑定模式下都和它们在 data模式下的工作方式一样,绑定和非绑定都这样

 

什么时候使用非绑定模式

基于行的非绑定模式被设计成在数据库 API和网格之间提供一个可使用的接口,如果你只是简单地需要显示和操作二维数据表,那么基于列的非绑定模式会显行很麻烦,下面的 DataMode设置之一会是更好的选择

3- Application,以每个单元格为基本单元触发事件

4- Storage,直接与一个 XarrayDB对象通信

模式 3和 4是特意为一个基于 array的数据源准备的,但是基于行的模式 1和模式 2 有更为显著的特点并且与任何数据源都能很好的工作

如果你操作的是一个 database 而不是一个 array,那么选择涉及到效率与易用性的对比。如果你关心的是效率,并且想把触发的事件减少到最小,你应该选择数据模式 2- Unbound Extended 。当使用支持 multiple-row fetches 的数据库 API时(如 ODBC),也推荐使用模式 2。你也可以使用模式 2来减少开销。例如:不要绑定到一个 RDC,取而代之的是在非绑定模式 2下使用 RDO 来生成带数据的网格,这些数据来自于一个 rdoResultSet对象

模式 3与模式 2更易于实现,但是效率会低,因为每 cell上的事件触发胜于每行的事件触发,如果速度和效率是你基本考虑的,那么模式 2是首选。

如果你开发的应用程序使用一个未绑定的网格,你应该考虑换到模式 2,因为它更有效。然而,如果你不想修改已有的 UnboundReadData事件处理过程,你可以在模式 1达到同样的性能提升,通过实现可选的 UnboundGetRelativeBookmark事件

 

非绑定模式如何工作

当 True DBGrid运行在非绑定模式时,它不连接到数据控件,取而代之的是,在网格处理所有的用户操作和数据显示时,你的应用程序必须提供并维护数据。例如:当一个用户用一个窗口盖住了网格,然后再移开,网格完全负责重画暴露的区域。你的应用程序不需要考虑低层的显示操作。

 

与之操作类似,在维护你的数据上,你需要单独的集中处理。在 DataMode 1 – Unbound,当网格需要取一列数据时,触发 UnboundReadData事件。让你的应用程序填充 RowBuffer对象,根据需要请求相应的值,作为一个事件参数传递。类似地,当用户重配置卷动框,网格需要决定行的书签

 

在模式 2―― Unbound Extended中,网格触发 UnboundReadDataEx事件,该事件联合了 UnboundReadData 和 UnboundGetRelativeBookmark 的功能。当网格第一次调入时,它会触发 UnboundReadDataEx事件为第一行接收书签(不是数据)。如果你的事件处理器提供一个书签,网格会再次触发 UnboundReadDataEx,这次是在一个十行的块里取出实际的数据。这个处理将持续到网格有足够的数据填入它的显示区或你的事件处理器提示网格已经到达数据集的末尾。因为用户可以通过网格卷动, UnboundReadDataEx事件在需要获得书签和数据时被触发。

UnboundReadDataEx事件的触发条件:

  1. 当网格控件第一次显示时;
  2. 当刷新 (Refresh)和重新绑定 (ReBind)时;
  3. 当网格控件被卷动时 (Scrolled);
  4. 在网格控件中一个记录被修改并且被用户确定(把光标移离当前行)之后

 

在 True DBGrid的非绑定模式下编程,与为 VB Form编写事件处理代理非常相似。你不能预料用户什么时候会点击按钮或从下拉框里选择一个项目,所以你的应用程序必须准备在任何时候处理这些事件。同样,你不能预料网格在什么时候会要求一个详细的数据和,或提供一个新的值来写到数据源。因为,处理非绑定模式事件的代码,例如: UnboundReadData 和 UnboundWriteData 应该被写到程序,以便它执行尽可能少地的任务

 

虽然网格也可以根据页面和卷动预测操作来缓冲一些列,但一般限制它的数据请求到显示单元。你无法预测网格将在什么时候请求数据,也不能假定数据会因为任何特殊目的被请求,此外,因为网格不会永久地保存数据,已经被你的程序请求过一次的数据也许会被再次请求。因此,你必须提供并维护你自己的数据仓库,因为网格不会为你做这些。

 

在模式 1和模式 2里添加行

True DBGrid不提供 AddNew方法,因为它不能预见下面数据源的请求。然而,在代码里添加了一行或多行后,你可以使用 ApproxCount属性和 ReOpen 方法来再同步网格。

下面的例子假设数据源是一个两维阵列表。它分配存储空间给一个新行,提示网格行的总数已经发生变化,然后调用 grid的 ReOpen方面来强制 grid重取数据并放置到新添加的行:

‘ General declarations

Dim MaxRow As Long

Dim MaxCol As Integer

Dim MyArray() As String

' Assume that MyArray is one-based

MaxRow = MaxRow + 1

ReDim Preserve MyArray(1 To MaxRow, 1 To MaxCol)

' Update the number of rows

TDBGrid1.ApproxCount = MaxRow

' ReOpen the data source and make MaxRow the current row

TDBGrid1.ReOpen MaxRow

 

 

自定义网格的外观

本节解释如何配置 True DBGrid 显示的不相关元素。例如: captions, headers, footers, record selectors, and dividing lines.

 

captions, headers, footers

你可以通过 Caption 属性把一个标题粘贴到网格、列、或 split

TDBGrid1.Caption = "Grid Caption"

TDBGrid1.Columns(0).Caption = "Column 0 Caption"

TDBGrid1.Splits(0).Caption = "Split 0 Caption"

因为 Grid的水平卷动一直会到最右边的列完全显示出来后才停,通常在最后一列与 Grid的右边界会有一块空白区域。你可以除去最右边的空白区域,用 ExtendRightColumn属性。该属性的缺省值是 False,但是如果你设为 True,那么最后一列就会扩展宽度到 Grid的右边。

 

未使用数据行:如果数据源包含的数据比 Grid能显示的内容少,那么在 AddNew行下面(或最后一行数据下面)会留出空白区域来。你可以用 EmptyRows属性去掉这个空白区域。该值缺省的是 False,但你可以把它设为 True,之后 Grid会在最后一个数据行下面显示空行来填满原来的空白区域。注意:那些空行不能接受焦点。

 

你可以同时设置 EmptyRows and ExtendRightColumn属性为 True来实现在一个 Grid里没有空白区域出现。没有数据显示的区域称为“ Dead Zone(死区 ) ”

 

当前被选中行或单元格的提示

MarqueeStyle 1 - Solid Cell Border 风格最接近 Excel,被选中的单元格被一个黑框包围

 

修正所有 Grid 行的高度

可以在设计的时候,也可在运行的时候设置。

TDBGrid1.RowHeight = 0

TDBGrid1.RowHeight = 3 * TDBGrid1.RowHeight

 

这种技术在显示多行的 memo 字段的时候特别有效。注意:列必须把 WrapText必性设为 True,否则, memo字段显示会被截掉。

 

在单元格里实现换行

缺省状态下, Grid 单元格只显示一个单行文本,会把右端以后的字截掉。通过拉宽列和设置 WrapText属性为 True ,你可以在一个单格里显示多行。如果 WrapText为 True,显示在单元格里的文字会自动断行,单元格内容会在第二行继续显示。可以用下面的方法为每列设置自动换行。

Dim C As TrueDBGrid60.Column

For Each C In TDBGrid1.Columns

C.WrapText = True

Next

 

或者,在设计的时候,把每一行的 WrapText属性设置为 True

 

在多行里显示一个记录

正常情况下,一个记录显示在一行里。如果网格的宽度不够显示记录里的所有列,一个水平卷动条支自动出现,让用户能够卷动查看。为了讨论目的,我们应该区别下面的两个概念:

  • 网格里的 Line是一个单元格组成的物理行。不要把这个与网格单元格里文本的一行搞混;根据 RowHeight and WrapText属性的设置,网格单元格里的数据以多行文本的方式显示。
  • 网格里的 row是用来显示一条记录的,一个 row可能包括多个 lines 或多个物理 row

Grid控件的 MultipleLines属性指定数据如何显示。缺省值是 0- Disabled,这意味着单条记录或行不能跨越多个 Line,如果需要,最终用户可以操作水平滚动条来浏览一行内所有列的数据。这就是 Grid如何正常显示数据的。

然而,如果 MultipleLines 属性设置为 1 - Variable or 2 – Fixed,那么单条记录就可以跨越多个 Line。该特性允许最终用户不用水平卷动,而在网格的宽度内同时浏览记录的所有列(字段)。

当 MultipleLines属性设置为 0 – Disabled以外的值,水平滚动条将会隐含掉,并且网格会自动跨越或换行到多行,这样所有列在网格的宽度内都能看到。如果列布局你不喜欢,你可以在设计时或运行时修改它的宽度和顺序。

1 - Variable and 2 – Fixed之间的区别会继续到运行时,当列或网格自己的宽度改变时。如果需要的话,以前的设置会重新调整列的断行;后面的设置保持列的断行。

Data Presentation Techniques(数据表达技术)

本节解释如何在各种各样的文字与图形格式里显示单元格数据。

 

Text Formatting

许多情况下, True DBGrid 从数据源收到的数据并不能满足给最终用户的显示。例如:数据字段可能需要转换到一个特定内部格式;货币字段可能在小数点后包含很多无意义的数字。因此, True DBGrid提供了对 VB 内部格式的访问,用 NumberFormat 属性可以为每一列指定格式。

True DBGrid提供一个事件- FormatText,可以让你的应用程序越过缺省格式

 

Using Visual Basic's built-in formatting

True DBGrid通过 Column对象的 NumberFormat属性支持多种数据格式的操作,和 Visual Basic的 Format$功能一样。例如:要根据 26-Apr-97的格式显示一列里的所有的日期数据,你可以使用 Medium Date设置:

TDBGrid1.Columns("HireDate").NumberFormat = "Medium Date"

 

注意:如果你在运行时改变列的 NumberFormat属性,你不需要刷新显示,因为 True DBGrid会自动处理。

 

Input validation with built-in formatting (内建格式输入确认)

要注意 NumberFormat 属性仅仅影响在网格里数据的显示,这很重要。除非你也为 EditMask属性指定一个值,否则 True DBGrid不会强制一个输入模板,并且用户可以自由输入任何东西到格式化过的单元里。当移动到另一个单元格的时候,网格将合理地解释用户的输入值,并修改数据库(如何需要的话),并且根据 NumberFormat属性的设置重新显示数据。

 

Formatting with an input mask (用输入掩码来格式化)

因为它对于输入和显示格式是一样的, NumberFormat属性有一个 Edit Mask选项。如果你选中这个选项,那么 Edit Mask属性设置将被用于数据输入和显示。然而,输入和显示格式需要不一样。

例如:下面的代码作用于一个电话号码的模板,这一列的数据显示和编辑

With TDBGrid1.Columns("Phone")

.EditMask = "(###) ###-####"

.NumberFormat = "Edit Mask"

End With

 

用自定义事件来格式化

在某些情况下,你可能发现 VB 的格式选项不能满足你的特殊需要,或者你也许正在一个不支持 VB格式的开发环境中使用 True DBGrid,例如 VC++。在这些情况下, FormatText事件选项可以指定 NumberFormat属性。选中这个选项将导致每次数据在被显示的那列时 FormatText事件被触发,该事件允许你重新格式化、转译或任何你想显示的数据格式:

Private Sub TDBGrid1_FormatText(ByVal ColIndex As Integer, _

Value As Variant, Bookmark As Variant)

ColIndex包含了要被重新格式化的网格列序号, Value包含了数据的值,也作为被格式化的显示值。例如:希望第一列包含从 1以 30的数字值,并且你希望显示罗马数字:

Private Sub TDBGrid1_FormatText(ByVal ColIndex As Integer, Value As Variant, Bookmark As Variant)

Dim result As String

If ColIndex = 0 Then

' Determine how many X's

While Value >= 10

result = result & "X"

Value = Value - 10

Wend

' Append "digits" 1-9

Select Case Value

Case 1

result = result & "I"

Case 2

result = result & "II"

Case 3

result = result & "III"

Case 4

result = result & "IV"

Case 5

result = result & "V"

Case 6

result = result & "VI"

Case 7

result = result & "VII"

Case 8

result = result & "VIII"

Case 9

result = result & "IX"

End Select

' Change the actual format

Value = result

End If

End Sub

 

因为 FormatText事件不受限于一个特殊的开发环境,你可以使用它获得完全的控制

 

 

Automatic Data Translation with ValueItems (自动数据转换)

虽然你能用 FormatText 事件来映射数据值到很多的描述显示值,但是 True DBGrid还提供了一个机制来执行例如无需代码的自动数据转译。通过使用 ValueItems集合,你可以指定适当的文本,甚至是图片显示在数据值的下面。

该特性完美地适用于显示数字代码或缩写,以一种对最终用户有意义的形式。例如:国家代码能被表示成适当的名字,甚至是他们各自的国旗图案;另外,数字 0、 1和 2能被显示成是、否和也许。实际值( 0、 1、 2)或转译值(是、否、也许)可以被显示为选项。

Database Programming Techniques

除了特别注明,本节的技术对所有 DataMode属性设置都有效。

 

Changing the Current Record Position

True DBGrid允许你在绑定或非绑定模式直接操作当前记录。要这样操作,你可能用 Bookmark属性或一种游历方法

 

Using the Bookmark property

当你在代码里设置 Bookmark属性为一个有效值时,这个值的相关行即成为当前行,网格修改显示把当前行放到显示区域里来。

 

Using the navigation methods

当网格被绑定到数据控件时,你可以用数据控件属性和方法来直接操作 Recordset,例如: EOF、 MoveFirst, and MoveNext,但是,如果你后来决定切换到非绑定数据源,这些属性和方法就会失效。

True DBGrid通过提供模拟 Recordset对象支持的属性和方法来解决这些问题。这些属性和方法对所有的 DataMode设定都有同样的工作方式,因此,排除了分别为绑定和非绑定模式单独编写代码的需要。

MoveFirst Moves the current record to the first record available.

MoveLast Moves the current record to the last record available.

MoveNext Moves the current record to the next record available.

MovePrevious Moves the current record to the previous record available.

MoveRelative Moves the current record according to a specified offset and optional bookmark.

 

只有 MoveRelative方法接受参数(一个长整型 Offset和一个可选的 variant bookmark)。一个正 Offset表示向前移动,负的 offset表示向后移动。如果 bookmark参数被省略了,将使用当前行的书签。因此,下面的语句是等效的:

TDBGrid1.MoveRelative -1, TDBGrid1.Bookmark

TDBGrid1.MoveRelative -1

TDBGrid1.MovePrevious

 

Detecting BOF and EOF conditions

在记录游历方法这外, True DBGrid提供了 BOF和 EOF属性来作为判断文件起始或结束的条件。例如:下面的循环反复通过所有有效记录。

With TDBGrid1

.MoveFirst

While Not .EOF

' Process current record

.MoveNext

Wend

End With


本文转载自网管联盟

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多