创建数据库感知组件 - TFieldDataLink.Edit会导致字段重新加载

时间:2014-01-28 20:49:23

标签: delphi vcl delphi-xe3

我正在尝试创建数据感知控件。我有一个TFieldDataLink对象,其中连接了DataSource和Field。在我尝试编辑值之前,一切似乎都没问题。

我正在为TFieldDataLink使用OnDataChange和OnUpdateData事件。如果我想在移动到新记录或发布之前调用OnUpdateData事件,我看起来需要调用TFieldDataLink.Edit。在下面的示例代码中,如果进行了更改,则尝试在控件的OnExit字段中调用.Edit。在我的实际应用程序中,控件包含几个DevExpress查找组合框,我试图在OnEditValueChanged中调用.Edit。

我的问题是对TFieldDataLink.Edit的调用导致OnDataChange事件再次触发。这会强制使用原始值重新加载我的编辑。如果我在数据集已经处于编辑模式后进行第二次更改,则不会触发OnDataChange事件。

这是一个测试单元,它包含一个表格上的所有内容。在我的实际应用程序中,这被分成一个更复杂的组件。

我应该何时调用.Edit而不更改OnUpdateData?我知道我可以在调用.Edit之前设置一个成员变量来停止重新加载或取消挂起事件。感觉就像我对TFieldDataLink对象有些不了解而且我不需要诉诸这些技巧。

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, uADStanIntf, uADStanOption, uADStanParam, uADStanError,
  uADDatSManager, uADPhysIntf, uADDAptIntf, Data.DB, uADCompDataSet, uADCompClient, Vcl.StdCtrls,
  Vcl.DBCtrls, Vcl.Mask, Vcl.ExtCtrls, Vcl.Grids, Vcl.DBGrids;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    DataSource1: TDataSource;
    ADMemTable1: TADMemTable;
    ADMemTable1test: TStringField;
    Button1: TButton;
    DBEdit1: TDBEdit;
    DBGrid1: TDBGrid;
    DBNavigator1: TDBNavigator;
    procedure FormCreate(Sender: TObject);
    procedure Edit1Exit(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FMyDataLink: TFieldDataLink;
    procedure MyDataChange(Sender: TObject);
    procedure MyUpdateData(Sender: TObject);
  public

  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  AdMemTable1.CreateDataSet;

  FMyDataLink := TFieldDataLink.Create();
  FMyDataLink.DataSource := DataSource1;
  FMyDataLink.FieldName := 'test';

  FMyDataLink.OnDataChange := MyDataChange;
  FMyDataLink.OnUpdateData := MyUpdateData;


  AdMemTable1.Append;
  AdMemTable1.FieldByName('test').AsString := 'my test';
  AdMemTable1.Post;


end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FMyDataLink.OnDataChange := nil;
  FMyDataLink.OnUpdateData := nil;
  FMyDataLink.Free;
end;

procedure TForm1.Edit1Exit(Sender: TObject);
begin
  if Edit1.Modified = true then
  begin
    FMyDataLink.Edit;
    FMyDataLink.Modified;
  end;
end;


procedure TForm1.MyDataChange(Sender: TObject);
begin
  Edit1.Text := FMyDataLink.Field.AsString;
  Edit1.Modified := false;
end;


procedure TForm1.MyUpdateData(Sender: TObject);
begin
  FMyDataLink.Field.AsString := Edit1.Text
end;


end.

2 个答案:

答案 0 :(得分:2)

TFieldDataLink.Edit仅将DataSource设置为编辑状态(就像DataSet.Edit)。你在这里不需要它,但示例用法可能是:

procedure TMyCustomControl.DoPaste;
begin
  FMyDataLink.Edit;
  inherited DoPaste;
  FMyDataLink.Modified;
end;

在退出控件时你想要的是更新记录,如果它被修改:

procedure TForm1.Edit1Exit(Sender: TObject);
begin
  if Edit1.Modified then
    try
      FMyDataLink.UpdateRecord;
    except
      Edit1.SetFocus;
      raise;
    end;
end;

至于何时应该调用TFieldDataLink.Modified,那就是你更新了字段值的时候:

procedure TForm1.MyUpdateData(Sender: TObject);
begin
  FMyDataLink.Field.AsString := Edit1.Text;
  FMyDataLink.Modified;
end;

答案 1 :(得分:2)

这是一个老问题,但对于那些遇到同样问题的人来说, 你必须覆盖数据感知控件的KeyPress方法并调用FieldDataLink.Edit;继承之后;如果密钥对输入有效(包括del / c& p / bs / etc ..)。 此时,当前数据尚未修改。在这之后调用.Edit为时已晚。