Einzelnen Beitrag anzeigen

hschmid67

Registriert seit: 2. Jul 2012
Ort: Weilheim i. Obb.
62 Beiträge
 
Delphi 10.4 Sydney
 
#1

Bookmark and DisableControls - ein kleiner Trick mit Interfaces

  Alt 1. Feb 2017, 14:18
Delphi-Version: 2009
Hallo zusammen,

ich bitte um Eure Meinung zu folgendem Vorgehen bei einem für mich alltäglichen Programmierfall:

Sehr häufig stehe ich vor der Situation, dass ich mit einem Dataset (meist eine Komponente auf einem Datenmodul) etwas tun möchte, was aber den Cursor im Dataset verändern wird. Da das Dataset noch mit anderen visuellen Komponenten verbunden ist, oder warum auch immer, möchte ich den Cursor aber beibehalten. Also mache ich oft folgendes:


Delphi-Quellcode:
procedure TuIrgendWas;
var
  lBookmark : TArray<Byte>;
begin
  lBookmark := Dataset.Bookmark;
  Dataset.DisableControls;
  try
    { tu hier irgendwas, z.B. }
    Dataset.First;
    while not Dataset.Eof do
    begin
      { z.B. Feld in Datensatz aktualsisieren }
      Dataset.Edit;
      Dataset.FieldByName('markiert').AsInteger := 1;
      Dataset.Post;
      Dataset.Next;
    end;
  finally
    Dataset.Bookmark := lBookmark;
    Dataset.EnableControls;
  end;
end;
Das allgemeine Muster ist also:

Delphi-Quellcode:
var
  lBookmark : TArray<Byte>;
begin
  lBookmark := Dataset.Bookmark;
  Dataset.DisableControls;
  try
    { tu hier irgendwas}
  finally
    Dataset.Bookmark := lBookmark;
    Dataset.EnableControls;
  end;
Meistens ist das dann auch schon alles in der jeweiligen Prozedur. Ich suchte also eine Möglichkeit, den Rahmen um die eigentliche Arbeit schöner zu machen. Dabei bin ich auf folgende Lösung gekommen:

Ich habe irgendwo ein Interface definiert, das ein Objekt repräsentiert, das sich beim Erzeugen sowohl das Bookmark als auch das Dataset merkt und DisableControls aufruft. Wenn man danach eh die Procedure verläßt, wird auch das Interface wieder freigegeben und dabei dann der Cursor/das Bookmark zurückgesetzt und EnableControls aufgerufen. Hier eine kleine Unit mit Interface und Classe:

Delphi-Quellcode:
unit uIntfTest;

interface

uses
  Data.DB;

type
  IDBTool = interface(IInterface)
    ['{D924218E-DF15-486F-9322-A989DEF76B50}']
  end;

  TDBTool = class(TInterfacedObject, IDBTool)
  private
    FBookmark: TArray<byte>;
    FDataSet: TDataSet;
    procedure BeginUpdate;
    procedure EndUpdate;
  public
    constructor Create(const mDataSet: TDataSet);
    destructor Destroy; override;
  end;

function BookmarkAndDisable(const mDataset: TDataSet): IDBTool;

implementation

function BookmarkAndDisable(const mDataset: TDataSet): IDBTool;
begin
  Result := TDBTool.Create(mDataset);
end;

constructor TDBTool.Create(const mDataSet: TDataSet);
begin
  inherited Create;
  FDataSet := mDataSet;
  BeginUpdate;
end;

destructor TDBTool.Destroy;
begin
  EndUpdate;
  inherited;
end;

procedure TDBTool.BeginUpdate;
begin
  FBookmark := FDataSet.Bookmark;
  FDataSet.EnableControls;
end;

procedure TDBTool.EndUpdate;
begin
  FDataSet.Bookmark := FBookmark;
  FDataSet.EnableControls;
end;

end.
Nun kann man den obigen Code so abkürzen:

Delphi-Quellcode:
procedure TuIrgendWas;
begin
  BookmarkAndDisable(Dataset);
  { tu hier irgendwas }
end;
Delphi kümmert sich beim Freigeben des Interfaces, also am Ende der Prozedur automatisch um das Zurücksetzen des Bookmarks und die Control-Aktualisierung. Wenn man es früher braucht, müsste man doch mit einer lokalen Variablen arbeiten:

Delphi-Quellcode:
procedure TuIrgendWas;
var
  lIntf: IDBTool;
begin
  lIntf := BookmarkAndDisable(Dataset);
  { tu hier irgendwas }
  lIntf := nil;
  { tu nochmal was }
end;

Was meint ihr? Ist das eine brauchbare Lösung? Gibt es irgendwelche Pferdefüße?
Harald Schmid
  Mit Zitat antworten Zitat