2015-02-12 108 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