从delphi中的另一个表单刷新DBGrid

时间:2015-05-10 10:01:40

标签: delphi dbgrid

我刚刚开始学习德尔福,而且我遇到了问题。我从另一个表单刷新DBGrid。我的代码:

Form1中:

unit uForm1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, ADODB, Grids, DBGrids, StdCtrls;

type
  TForm1 = class(TForm)
    btnAdd: TButton;
    grid: TDBGrid;
    ADOQuery1: TADOQuery;
    DataSource1: TDataSource;
    procedure btnAdd(Sender: TObject);
  private
  public
       constructor Create(Owner:TComponent); overload;
  end;

var
  form1: TForm1;

implementation

uses uForm2, uDbOperations;

{$R *.dfm}

procedure TForm1.btnAddClick(Sender: TObject);
var
  frm : TForm2;
begin
  frm := TForm2.Create(form1);
  frm.ShowModal;
  frm.Free;
end;

窗体2:

unit uForm2;
procedure TForm2.btnAddClick(Sender: TObject);
var
  query : string;
begin
       query := 'Insert into Employees(Name) Values('''+txtName.Text+''');';
       DbOperations.InsertOrUpdate(query, ADOQuery1);
        ModalResult := mrCancel;
        //And this here I'd refresh grid on form1           
end;
end.

如何在form2中添加记录后,在form1中刷新dbgrid?我尝试了很多方法,但没有成功。我知道在C#中需要在构造函数中传递引用,但delphi如何?

3 个答案:

答案 0 :(得分:4)

使用你的模式,我会做这样的事情:

procedure TForm1.btnAddClick(Sender: TObject);
var
  frm : TForm2;
begin
  frm := TForm2.Create(form1);
  try
    if frm.ShowModal = mrOK then
    begin
      Grid.Datasource.Dataset.Refresh;
      // some databases require open/close to refresh
      // in this case Grid.Datasource.Dataset.close;
      //              Grid.Datasource.Dataset.Open;
    end;
  finally
    frm.Free;
  end
end;

procedure TForm2.btnAddClick(Sender: TObject);
var
  query : string;
begin
  query := 'Insert into Employees(Name) Values('''+txtName.Text+''');';
  DbOperations.InsertOrUpdate(query, ADOQuery1);
  ModalResult := mrOK;
  // let a cancel button on Form2 perform ModalResult = mrCancel  
  // to avoid unnecessary dataset refreshes..      
end;

答案 1 :(得分:1)

解决从其他单元执行代码问题的更通用方法只是向TForm2添加事件。

 TForm2 = class(TForm)
 private
   FOnDataInserted : TNotifyEvent;
 public
   property OnDataInserted : TNotifyEvent read FOnDataInserted write FOnDataInserted;
 end;

将此事件实施为:

procedure TForm2.btnAddClick(Sender: TObject);
var
  query : string;
begin
  query := 'Insert into Employees(Name) Values('''+txtName.Text+''');';
  DbOperations.InsertOrUpdate(query, ADOQuery1);
  ModalResult := mrCancel;
  //And this here I'd refresh grid on form1
  If Assigned(FOnDatabaseInsert) then FOnDatabaseInsert(self);                
end;

现在,要为事件分配一个方法,在TForm1中,声明一个合适的方法来处理它:

procedure TForm1.Form2DataInserted(Sender: TObject);
begin
  // do something, update grid, etc...
end;

创建表单时:

procedure TForm1.btnAddClick(Sender: TObject);
var
  frm : TForm2;
begin
  frm := TForm2.Create(form1);
  try
    frm.OnDataInserted := Form2DataInserted;
    frm.ShowModal;
  finally
    frm.Free;
  end;
end;

此模型允许您在代码中的任何位置执行任何类型的回调。这是依赖注入的一种形式,因为拥有组件提供了方法 - TForm2不包含对TForm1的任何引用,因此此方法保留了单元的隔离。

正如其他人在评论中指出的那样,这可能不是解决特定问题的理想解决方案,但它确实回答了直接问题,并提供了一种在类和单元边界之间干净地调用代码的方法。

答案 2 :(得分:0)

简单的黑客方式,而不是我会做的事情

 (FOwner as TForm1).grid.refresh

建议的方法是在创建FreeNotification

后注册Form2
Forms.FreeNotification(Self).

Form1被销毁时,这会向Form2发送通知方法。在Form1中,您添加一个事件

protected
  procedure Notification(AComponent: TComponent; Operation: TOperation); override;

实施中

procedure TForm1.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited;
  if (AComponent is TForm) and (Operation = opRemove) then
  begin
    grid.Refresh;
  end;
end; 

注意我没有使用它,但它应该可以工作。