Delphi 创建DB感知组件-TFieldDataLink.Edit会导致重新加载字段

Delphi 创建DB感知组件-TFieldDataLink.Edit会导致重新加载字段,delphi,vcl,delphi-xe3,Delphi,Vcl,Delphi Xe3,我正在尝试创建一个数据感知控件。我有一个连接了数据源和字段的TFieldDataLink对象。在我尝试编辑值之前,一切似乎都正常 我正在为TFieldDataLink使用OnDataChange和OnUpdateData事件。如果我想在移动到新记录或过帐之前调用onUpdate数据事件,则需要调用TFieldDataLink.Edit。在下面的示例代码中,如果进行了更改,我将尝试在控件的OnExit字段中调用.Edit。在我的实际应用中,该控件由几个DevExpress查找组合框组成,我正在尝试

我正在尝试创建一个数据感知控件。我有一个连接了数据源和字段的TFieldDataLink对象。在我尝试编辑值之前,一切似乎都正常

我正在为TFieldDataLink使用OnDataChange和OnUpdateData事件。如果我想在移动到新记录或过帐之前调用onUpdate数据事件,则需要调用TFieldDataLink.Edit。在下面的示例代码中,如果进行了更改,我将尝试在控件的OnExit字段中调用.Edit。在我的实际应用中,该控件由几个DevExpress查找组合框组成,我正在尝试调用。在OnEditValueChanged中编辑

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

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

我应该什么时候打电话。编辑而不获取要更改的更新数据?我知道我可以在调用.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.
仅将数据源设置为编辑状态,就像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;
至于什么时候应该被调用,也就是您更新字段值的时候:

procedure TForm1.MyUpdateData(Sender: TObject);
begin
  FMyDataLink.Field.AsString := Edit1.Text;
  FMyDataLink.Modified;
end;
仅将数据源设置为编辑状态,就像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;
至于什么时候应该被调用,也就是您更新字段值的时候:

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

这是一个老问题,但对于那些遇到同样问题的人来说, 您必须覆盖数据感知控件的按键方法,并调用FieldDataLink.Edit;继承后;如果该键对输入有效,包括del/c&p/bs/等。。。
此时,当前数据尚未修改。打电话。迟于此点编辑已经太晚了。

这是一个老问题,但对于遇到同样问题的人来说, 您必须覆盖数据感知控件的按键方法,并调用FieldDataLink.Edit;继承后;如果该键对输入有效,包括del/c&p/bs/等。。。
此时,当前数据尚未修改。如果调用FMyDataLink.UpdateRecord而不调用FMyDataLink.Edit,则调用.Edit晚于此点已为时过晚。

如果调用FMyDataLink.UpdateRecord而不首先调用FMyDataLink.Edit,则不会调用UpdateData事件,因此数据集永远不会更新。我不想立即将数据集置于编辑模式。我想像其他db组件一样等待第一次更改。我只是不知道如何才能不丢失第一个更改。如果在OnExit处理程序中尚未调用FMyDataLink.Modified,那么thatát就是您的问题。OnExit不需要发出改变的信号;例如,编辑的OnChange处理程序仍然不起作用。设置Modified似乎只能确保为该字段调用UpdateData。只有调用Edit时才会发生这种情况,这又回到了我的问题,即在第一次更改后调用Edit会导致重新加载。在TEdit的情况下,如果我在OnChange事件中调用DataLink.Edit并尝试在字段末尾键入一个字母,则在重新加载时,我的编辑将被清除,光标将移回文本的前面。如果您在不调用FMyDataLink的情况下调用FMyDataLink.UpdateRecord。首先编辑,则不会调用UpdateData事件,因此数据集不会被调用永远不会更新。我不想立即将数据集置于编辑模式。我想像其他db组件一样等待第一次更改。我只是不知道如何才能不丢失第一个更改。如果在OnExit处理程序中尚未调用FMyDataLink.Modified,那么thatát就是您的问题。OnExit不需要发出改变的信号;例如,编辑的OnChange处理程序仍然不起作用。设置Modified似乎只能确保为该字段调用UpdateData。只有调用Edit时才会发生这种情况,这又回到了我的问题,即在第一次更改后调用Edit会导致重新加载。在TEdit的情况下,如果我在OnChange事件中调用DataLink.Edit,并尝试在字段末尾键入字母,则在重新加载时,我的编辑将被清除,光标将移回文本的前面。