首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

3.8  TField对象的SetTextGetText事件处理函数

在许多数据库设计中,分析师都会使用键值来代表特定的信息,例如使用ID值来代表部门代号,使用书籍号码来代表书名等。这些技巧有几个目的,其中最重要的目的是在数据表中维持唯一的特性,以方便查寻特定的数据。其他的则可能是为了数据库范式化的目的(不是所有的分析师都知道数据库范式化),也有可能是为了节省数据库储存空间等。

虽然上述的设计很正确,但是在用户使用应用程序时却可能不希望看到对用户无意义的键值代号,而是希望看到完整的信息。例如用户可能希望看到完整的书籍名称,而不是书籍代号,除非这个用户是书商,能够熟记每一个书籍代号代表的书籍,因此,解决这个数据库中信息转换的工作是许多数据库应用程序都需要处理的。

要解决这个问题有许多不同的方法,DelphiTField对象也提供了两个相关的事件处理函数SetText以及GetText来帮助程序员解决这个问题。GetText事件被触发的时机是当客户端需要取得字段的数值时,因此,键值的字段程序员就可以在这个事件处理函数中使用键值到其他数据表中查寻这个键值代表的完整信息,再把此完整信息回传当成字段的数值即可。下面是GetText的声明原型:

type TFieldGetTextEvent = procedure(Sender: TField; var Text: String; DisplayText: Boolean) of object;

TFieldGetTextEvent的第一个参数Sender便是目前要取得数值的字段,第二个参数Text是声明为var类型的字符串参数,程序员必须在这个参数中指定代表此字段的数值,最后一个参数DisplayText则是用来代表这个字段是使用来显示的或是允许用户修改的。

如果程序员使用了GetText事件处理函数转换字段的代表数值,那么程序员通常就需要搭配SetText事件处理函数。因为当GetText改变字段代表的数值之后,用户如果在客户端修改了这个字段的数据,并且在用户把数据更新回数据来源中时,程序员必须把数据转换回原始的格式,再更新到数据来源中。而进行这个数据回转的好地方就是SetText事件处理函数。

SetText事件的声明原型如下:

type TFieldSetTextEvent = procedure(Sender: TField; const Text: String) of
  object
;

其中的第一个参数Sender是要更新数据的字段,而Text则是客户端传递来的代表此字段的数值,程序员可以使用参数Text的数值恢复成正确的数据,再把这个正确的数据指定给SenderValue特性值。

现在让我们使用一个范例来说明如何使用GetTextSetText事件处理函数。在D2006HDBP数据库中,BOOKS数据表有一个字段AID代表书籍的作者或是唱片的歌手,当我们使用数据感知控件显示BOOKS数据表时,我们并不希望看到AID的数值,而是希望看到AID代表的人名。因此,这个范例在使用TDBGrid显示BOOKS数据表的内容时,就使用了GetTextSetText事件处理函数来转换AID成人名,并且在用户更改数据时根据人名再转成正确的AID数值,并更新回BOOKS数据表之中。

首先建立一个Delphi项目,在数据模块中放入如下的dbExpress控件以连接D2006HDBP数据库(见图3-27)。

3-27  使用dbExpress连接D2006HDBP

TSQLConnection

特性名称

设定特性值

Name

D2006HDBP

Database

F:\My Books\dbExpress 2006\D2006HPDBP\Data\d2006hpdbp.gdb

TSimpleDataSet

特性名称

设定特性值

Name

sdsBooks

DBConnection

D2006HDBP

DataSet\CommandText

select * from BOOKS

TSQLDataSet

特性名称

设定特性值

Name

sqldsPerformersByID

DBConnection

D2006HDBP

CommandText

select NAME from PERFORMERS where AID = :AID

TSQLDataSet

特性名称

设定特性值

Name

sqldsPerformersByName

DBConnection

D2006HDBP

CommandText

select AID from PERFORMERS where NAME = :NAME

TSQLDataSet

特性名称

设定特性值

Name

sqldsGeneral

DBConnection

D2006HDBP

接着启动sdsBooks的字段编辑器加入所有的字段,并且使用对象查看器为AID字段定义GetTextSetText,如图3-28所示。

3-28  启动sdsBooks的字段编辑器,加入所有字段,再设定AID字段的GetTextSetText事件处理函数

现在我们希望使用TDBGrid显示BOOKS数据表的内容,并且希望AID字段能够显示一个下拉框允许用户在更改此字段的数据时能够使用选择人名的方式。因此在主窗体中加入一个TDBGrid控件,双击TDBGrid启动字段编辑器,加入所有的字段如图3-29所示。由于我们希望在此字段能够让用户选择人名,因此我们只需要把人名的数据加入到图3-29AIDPickList特性值之中即可。

3-29  启动sdsBooks的字段编辑器,加入所有字段,再设定AID字段的GetTextSetText事件处理函数

首先我们实现数据模块中AID字段的GetTextSetText字段的事件处理函数。下面即是相关的实现程序代码:

procedure TdmSetGetTextDemo.sdsBooksAIDGetText(Sender: TField;

  var Text: String; DisplayText: Boolean);

begin

  try

    Self.sqldsPerformersByID.ParamByName('AID').Value := Sender.Value;

    Self.sqldsPerformersByID.Active := True;

    Text := Self.sqldsPerformersByID.Fields[0].AsString;

  finally

    Self.sqldsPerformersByID.Active := False;

  end;

end;

 

procedure TdmSetGetTextDemo.DataModuleCreate(Sender: TObject);

begin

  Self.sqldsPerformersByID.Prepared := True;

  Self.sqldsPerformersByName.Prepared := True;

end;

 

procedure TdmSetGetTextDemo.DataModuleDestroy(Sender: TObject);

begin

  Self.sqldsPerformersByID.Active := False;

  Self.sqldsPerformersByID.Prepared := False;

  Self.sqldsPerformersByName.Active := False;

  Self.sqldsPerformersByName.Prepared := False;

 

  Self.D2006HDBP.Connected := False;

end;

 

procedure TdmSetGetTextDemo.sdsBooksAIDSetText(Sender: TField;

  const Text: String);

begin

  try

    Self.sqldsPerformersByName.ParamByName('NAME').Value := Text;

    Self.sqldsPerformersByName.Active := True;

    Sender.Value := Self.sqldsPerformersByName.Fields[0].Value;

  finally

    Self.sqldsPerformersByName.Active := False;

  end;

end;

sdsBooksAIDGetText事件处理函数中,我们根据AID字段目前的数值到PERFORMERS数据表中查寻代表此ID的人名信息,再把找到的人名指定给第二个参数Text。而sdsBooksAIDSetText事件处理函数则是执行相反的工作,它根据传递来的人名数据,再回到PERFORMERS数据表中查寻此人名的AID数值,最后再指定给代表字段对象的Sender参数的Value特性值。

GetTextSetText事件处理函数执行的次数非常地频繁,为了增加执行效率,我们分别在数据模块的OnCreate事件处理函数中先Prepare sqldsPerformersByIDsqldsPerformersByName控件要执行的SQL语句,并且在数据模块的OnDestroy事件处理函数中Unprepare,以释放数据来源中使用的资源。

最后再回到范例程序的主窗体中,其中主要的工作就是显示TDBGrid时在AID字段的PickList中填入目前在PERFORMERS数据表中所有的人名信息,这个工作是在范例主窗体的OnShow事件处理函数中调用FillPerformerInfos函数完成的。而FillPerformerInfos函数则是使用数据模块中的sqldsGeneral控件执行SQL语句,从PERFORMERS数据表中取得所有的人名数据,再填入到TDBGridAID字段的PickList特性值之中。

procedure TForm1.BitBtn2Click(Sender: TObject);

begin

  if (dmSetGetTextDemo.sdsBooks.ChangeCount > 0) then

    dmSetGetTextDemo.sdsBooks.ApplyUpdates(0);

end;

 

procedure TForm1.FillPerformerInfos;

begin

  if (Self.DBGrid1.Columns.Items[7].PickList.Count = 0) then

  begin

    dmSetGetTextDemo.sqldsGeneral.Active := False;

    dmSetGetTextDemo.sqldsGeneral.CommandText := 'select distinct NAME from PERFORMERS';

    try

      dmSetGetTextDemo.sqldsGeneral.Active := True;

      while not dmSetGetTextDemo.sqldsGeneral.Eof do

      begin

        Self.DBGrid1.Columns.Items[7].PickList.Add(dmSetGetTextDemo.sqldsGeneral.Fields[0].AsString);

        dmSetGetTextDemo.sqldsGeneral.Next;

      end;

    finally

      dmSetGetTextDemo.sqldsGeneral.Active := False;

    end;

  end;

end;

 

procedure TForm1.FormShow(Sender: TObject);

begin

  FillPerformerInfos;

end;

最后我们编译此范例并且执行它,那么用户便可以看到类似如图3-30所示的画面,请注意此时AID字段显示的不再是代表人名的ID数值,而是完整的人名数据,而且用户可以使用下拉框的方式来进行数据更改的工作。如果用户修改了AID字段中人名的数据并且点击主窗体中的ApplyUpdates按钮,那么数据模块中的SetText事件处理函数便会被触发,再把人名回转成正确的ID数值并更新回BOOKS数据表的AID字段之中。

3-30  范例程序执行的画面

当然,本范例只是为了展示如何使用GetTextSetText这两个事件处理函数,对这个范例来说,由于PERFORMERS数据表中的数据并不多,因此对于这种需要查询的数据表而言,如果数据量不多的话,那么程序员可以使用一个TSimpleDataSet/TClientDataSet把数据先存取到客户端,再于GetTextSetText事件处理函数中直接使用TSimpleDataSet/TClientDataSetLocate方法来进行数据转换的工作,这样可能会比较有效率。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论