2015-02-12 109 views
-1

为了理解接口,我已经实现了一个带窗体的小应用程序,一个带有简单数据库的数据模块。 这里是形式再次通过德尔福接口

enter image description here

的数据模块只包含一个连接,一个桌子和一个tdataSource组件。

接口单元是这样的:

unit databaseInterface; 

interface 

uses 
    MSAccess; 

type 
    IDBTest = interface 
    ['{5B8CF4FF-66F7-402D-8E18-0159CB22F805}'] 
    procedure SetTable(table: TMSTable); 
    function SetPriorRecord: Boolean; 
    function SetNextRecord: Boolean; 
    end; 

implementation 

end. 

和它的实现是这样的:

unit databaseImplementation; 

interface 

uses 
    databaseInterface, database, MSAccess; 

type 
    TDBTest = class(TInterfacedObject, IDBTest) 
    protected 
    DBTable: TMSTable; 
    FbtnPriorStatus: Boolean; 
    procedure SetTable(Table: TMSTable); 
    function SetPriorRecord: Boolean; 
    function SetNextRecord: Boolean; 
    public 
    property Table: TMSTable read DBTable write SetTable; 
    end; 

implementation 

{ TDBTest } 

procedure TDBTest.SetTable(Table: TMSTable); 
begin 
    if DBTable <> Table then begin 
    DBTable := Table; 
    DBTable.Open; 
    end; 
end; 

function TDBTest.SetPriorRecord: Boolean; 
begin 
    if not DBTable.Bof then begin 
    DBTable.Prior; 
    Result := DBTable.Bof; 
    end else 
    Result := True; 
end; 

function TDBTest.SetNextRecord: Boolean; 
begin 
    if not DBTable.Eof then begin 
    DBTable.Next; 
    Result := DBTable.Eof; 
    end else 
    Result := True; 
end; 

end. 

现在,这是个问题。我的窗体的代码如下:

unit main; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, 
    System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, 
    Vcl.ExtCtrls, databaseInterface, databaseImplementation, JvExMask, 
    JvToolEdit, JvMaskEdit, JvCheckedMaskEdit, JvDatePickerEdit, 
    Vcl.StdCtrls, Vcl.Mask, Vcl.DBCtrls, JvDBDatePickerEdit, JvExControls, 
    JvButton, JvTransparentButton, database; 

type 
    TfrmMain = class(TForm) 
    pnlCommands: TPanel; 
    pnlData: TPanel; 
    pnlMessages: TPanel; 
    bvlIcons: TBevel; 
    bvlNavigation: TBevel; 
    lblId: TLabel; 
    lblFirstName: TLabel; 
    lblLastName: TLabel; 
    lblBirthday: TLabel; 
    edtId: TDBEdit; 
    edtFirstName: TDBEdit; 
    edtLastName: TDBEdit; 
    dtpBirthday: TJvDBDatePickerEdit; 
    btnPrior: TJvTransparentButton; 
    btnNext: TJvTransparentButton; 
    procedure btnNextClick(Sender: TObject); 
    procedure btnPriorClick(Sender: TObject); 
    procedure FormCreate(Sender: TObject); 
    procedure FormActivate(Sender: TObject); 
    private 
    DBTest: IDBTest; 
    public 
    { Public declarations } 
    end; 

var 
    frmMain: TfrmMain; 

implementation 

{$R *.dfm} 

procedure TfrmMain.FormCreate(Sender: TObject); 
begin 
    DBTest := TDBTest.Create; 
end; 

procedure TfrmMain.FormActivate(Sender: TObject); 
begin 
    DBTest.SetTable(dmAuthors.tblAuthors); 
end; 

procedure TfrmMain.btnPriorClick(Sender: TObject); 
begin 
    btnPrior.Enabled := not DBTest.SetPriorRecord; 
    btnNext.Enabled := True; 
end; 

procedure TfrmMain.btnNextClick(Sender: TObject); 
begin 
    btnNext.Enabled := not DBTest.SetNextRecord; 
    btnPrior.Enabled := True; 
end; 

end. 

因此,我调用的方法SetPriorRecordSetNextRecord当用户点击了相关的按钮,然后,相应地与表的状态(BOF或EOF ),我禁用或启用按钮。 我想知道是否有方法通过接口设置按钮状态,从表单中解耦此操作;例如以任何方式或其他方式绑定按钮,但我不知道如何去做,如果可能的话! 我希望我对问题的解释很清楚。

+0

_I不知道是否有方法通过接口设置按钮状态,将此操作与form_解耦。这是一件非常容易的事情,并且有很多方法可以实现它。但我强烈建议不要将它与表单分开:按钮是UI的一部分,您的目标应该是将您的**业务逻辑**与UI分离。想想如果您决定将按钮从JvTransparent按钮更改为某种其他类型的按钮,会发生什么情况。您不希望您的业务代码被强制更改。 – 2015-02-12 15:05:22

回答

0

现有的接口是不够的。您需要传递让客户端知道表的状态的一些方法,但不暴露TDataSet的详细逻辑(最好)。对事件处理程序的回调将起作用;一个触发TAction的方法将起作用;就像一个匿名方法一样。你基本上需要返回一个表示BOF,EOF或者介于两者之间的某种标志;也可能是一个记录#和记录数。

+0

嗨大卫,谢谢你的回答,但我不是匿名方法的专家,所以,你可以请张贴一个小例子吗? – Eros 2015-02-12 10:21:03

+0

我可以,但我建议你坚持你所知道的。我重新回答了答案,所以可能会更清楚些。您使用的确切回调机制是不相关的。重点是,客户端需要知道数据集的状态以设置按钮。它只能知道,如果你的界面有一种方式返回它。有四种或五种不同的方式来做到这一点。我建议你尝试一下,如果你遇到问题,请发布你所做的并寻求帮助。这真的不是那么难,寿。 – 2015-02-12 23:26:43

0

我已经修改了应用程序接口以这样的方式

unit databaseInterface; 

interface 

uses 
    MSAccess; 

type 

    IDBTest = interface 
    ['{5B8CF4FF-66F7-402D-8E18-0159CB22F805}'] 
    procedure SetTable(table: TMSTable); 
    procedure SetPriorRecord; 
    procedure SetNextRecord; 
    function GetIsBof: Boolean; 
    function GetIsEof: Boolean; 
    property IsBof: Boolean read GetIsBof; 
    property IsEof: Boolean read GetIsEof; 
    end; 

implementation 

end. 

,这是实现接口:

unit databaseImplementation; 

interface 

uses 
    databaseInterface, database, MSAccess; 

type 
    TDBTest = class(TInterfacedObject, IDBTest) 
    protected 
    DBTable: TMSTable; 
    FIsBof: Boolean; 
    FIsEof: Boolean; 
    procedure SetTable(Table: TMSTable); 
    procedure SetPriorRecord; 
    procedure SetNextRecord; 
    function GetIsBof: Boolean; 
    function GetIsEof: Boolean; 
    procedure SetCursorStatus; 
    public 
    property Table: TMSTable read DBTable write SetTable; 
    property IsBof: Boolean read GetIsBof; 
    property IsEof: Boolean read GetIsEof; 
    end; 

implementation 

{ TDBTest } 

procedure TDBTest.SetTable(Table: TMSTable); 
begin 
    if DBTable <> Table then begin 
    DBTable := Table; 
    DBTable.Open; 
    end; 
end; 


procedure TDBTest.SetPriorRecord; 
begin 
    try 
    DBTable.Prior; 
    finally 
    SetCursorStatus; 
    end; 

end; 

procedure TDBTest.SetNextRecord; 
begin 
    try 
    DBTable.Next; 
    finally 
    SetCursorStatus; 
    end; 
end; 

procedure TDBTest.SetCursorStatus; 
begin 
    FIsBof := DBTable.Bof; 
    FIsEof := DBTable.Eof; 
end; 

function TDBTest.GetIsBof: Boolean; 
begin 
    Result := FIsBof; 
end; 

function TDBTest.GetIsEof: Boolean; 
begin 
    Result := FIsEof; 
end; 

end. 

所以表单代码变成这样:

unit main; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, 
    System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, 
    Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.Mask, Vcl.DBCtrls, JvExMask, JvToolEdit, 
    JvMaskEdit, JvCheckedMaskEdit, JvDatePickerEdit, JvDBDatePickerEdit, 
    JvExControls, JvButton, JvTransparentButton, database, databaseInterface, 
    databaseImplementation; 

type 

    TfrmMain = class(TForm) 
    pnlCommands: TPanel; 
    pnlData: TPanel; 
    pnlMessages: TPanel; 
    bvlIcons: TBevel; 
    bvlNavigation: TBevel; 
    lblId: TLabel; 
    lblFirstName: TLabel; 
    lblLastName: TLabel; 
    lblBirthday: TLabel; 
    edtId: TDBEdit; 
    edtFirstName: TDBEdit; 
    edtLastName: TDBEdit; 
    dtpBirthday: TJvDBDatePickerEdit; 
    btnPrior: TJvTransparentButton; 
    btnNext: TJvTransparentButton; 
    procedure btnNextClick(Sender: TObject); 
    procedure btnPriorClick(Sender: TObject); 
    procedure FormCreate(Sender: TObject); 
    procedure FormActivate(Sender: TObject); 
    private 
    DBTest: IDBTest; 
    procedure SetNavButtonsStatus; 
    public 
    { Public declarations } 
    end; 

var 
    frmMain: TfrmMain; 

implementation 

{$R *.dfm} 

procedure TfrmMain.FormCreate(Sender: TObject); 
begin 
    DBTest := TDBTest.Create; 
end; 

procedure TfrmMain.FormActivate(Sender: TObject); 
begin 
    DBTest.SetTable(dmAuthors.tblAuthors); 
end; 


{ Begin table navigation ----------------------------------------------------- } 

procedure TfrmMain.btnPriorClick(Sender: TObject); 
begin 
    DBTest.SetPriorRecord; 
    SetNavButtonsStatus; 
end; 

procedure TfrmMain.btnNextClick(Sender: TObject); 
begin 
    DBTest.SetNextRecord; 
    SetNavButtonsStatus; 
end; 

procedure TfrmMain.SetNavButtonsStatus; 
begin 
    btnPrior.Enabled := not DBTest.IsBof; 
    btnNext.Enabled := not DBTest.IsEof 
end; 

{ End table navigation ------------------------------------------------------- } 

end. 

现在我认为按钮是分离的,但我不确定我找到的解决方案。它可以很好吗?

+1

这是一个答案或问题? – 2015-02-15 20:16:08