Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Trennung von Darstellung und Daten, Prinzipfrage konkret (https://www.delphipraxis.net/160754-trennung-von-darstellung-und-daten-prinzipfrage-konkret.html)

haentschman 30. Mai 2011 08:27

Trennung von Darstellung und Daten, Prinzipfrage konkret
 
Hallo alle miteinander...

Mir geht es um "wie ist es richtig"... 8-)

Ich habe:
- eine Klasse "Test"
- "Test" holt dich aus der Datenbank die Daten und legt die DS in eine Objektlist
- die Objektlist wird in eine Listview eingelesen
- die Objekte liegen auch komplett in Data der Listview

soweit so gut...

Nehmen wir an die Daten werden editiert. Wo werden die Daten geändert ?
Variante 1:
- Änderung des Objektes in Data und bei "Speichern" Data komplett in "Test" zurück.

Variante 2:
- Änderung der Daten direkt im Objekt in "Test" und die Listview komplett neu einlesen.
--> Daten in "Test" sind immer aktuell.

Welches ist der sauberste Weg. Ich habe mich für Variante 2 entschieden. Was meint ihr ?

Danke für Infos...:hi:

Nachtrag: Data ist ein Pointer. Heißt das, daß die Referenz auf die Objektlist in Test zeigt ? Bzw. Data ja keine Kopie des Objektes enthällt. Dann wäre es ja wurscht wo man die Daten ändert...

mkinzler 30. Mai 2011 08:36

AW: Trennung von Darstellung und Daten, Prinzipfrage konkret
 
Da Test die Modellklasse ist, ist sie auch für die Daten verantwortlich.

haentschman 30. Mai 2011 08:37

AW: Trennung von Darstellung und Daten, Prinzipfrage konkret
 
Danke für die schnelle Antwort...
Wenn ich dich richtig verstehe, bin ich mit Variante 2 richtig.
:hi:

Memnarch 30. Mai 2011 08:38

AW: Trennung von Darstellung und Daten, Prinzipfrage konkret
 
Grundsätzlich hab ich es so gelernt, dass ich für meine Daten eine DatenKlasse schreibe(sofern eine extra struktur von nöten), von der wiederum ich mir die Infos hole, die ich zum anzeigen in meiner visuellen komponennte brauche. Dementsprechen würde ich das editieren der Daten in dem object Test vorziehen und danach dementsprechen die daten in der visuellen komponennte aktualisieren.

Bin aber noch Azubi im ersten Jahr...lass dir das lieber von wem anders bestätigen, vllt werf ich auch was durcheinander :stupid:

EDIT: ah MKinzler hats schon beantwortet^^


MFG
Memnarch

haentschman 30. Mai 2011 08:40

AW: Trennung von Darstellung und Daten, Prinzipfrage konkret
 
Danke Euch allen... :hi:

DeddyH 30. Mai 2011 08:40

AW: Trennung von Darstellung und Daten, Prinzipfrage konkret
 
Ich nehme an, Du meinst mit Data TListItem.Data. Dadurch, dass Du die Objekte dort ablegst und zusätzlich noch in einer Objektlist hälst Du je Objekt 2 Referenzen. Das kann gefährlich werden, wenn man nicht aufpasst. Sofern die Daten nicht auch noch anderweitig verwendet werden würde ich die Objektliste knicken und die Referenzen komplett in der Listview halten. Du musst dann nur darauf achten, dass Du beim Löschen der Items auch die Objekte wieder freigibst. Und zum Bearbeiten: der einzelne Datensatz (also die Daten des Objektes vom Typ Test) wird geändert, also muss man anschließend ggf. das zugehörige Item Refreshen, aber eben nur dieses und nicht die komplette Listview.

haentschman 30. Mai 2011 08:46

AW: Trennung von Darstellung und Daten, Prinzipfrage konkret
 
Hallo DeddyH...

ich hätte lieber die Objekte in der Objektlist, da die Klasse auch das Speichern in die DB erledigt.
...also eher auf Data verzichten.

DeddyH 30. Mai 2011 08:53

AW: Trennung von Darstellung und Daten, Prinzipfrage konkret
 
Dann hast Du aber das Problem, die Daten dem jeweiligen ListItem irgendwie anders sicher zuordnen zu müssen.

stahli 30. Mai 2011 12:37

AW: Trennung von Darstellung und Daten, Prinzipfrage konkret
 
Zitat:

Zitat von haentschman (Beitrag 1103626)
Nachtrag: Data ist ein Pointer. Heißt das, daß die Referenz auf die Objektlist in Test zeigt ? Bzw. Data ja keine Kopie des Objektes enthällt. Dann wäre es ja wurscht wo man die Daten ändert...

Genau. Ich habe nicht verstanden, was Du eigentlich meinst, aber Dein Nachtrag erklärt das.
Beide Objektpointer zeigen auf das gleiche Objekt (bzw. Speicherstelle). Also beziehen sich Datenänderungen immer auf beide Objektvariablen.

Das Problem ist dann nur, falls Du die Daten z.B. an zwei Stellen darstellt, bei Änderungen auch beide Stellen aktualisiert darzustellen.
Das wird üblicherweise über Observer-Pattern gelöst. Ich nutze statt dessen Controller-Komponenten, die von der Datenschicht Änderungsinfos erhalten und ihr angebundenes Control veranlassen, sich ggf. neu darzustellen. Dadurch muss ein Datenobjekt nicht eine Liste von registrierten sichtbaren Contzrols verwalten.

Namenloser 30. Mai 2011 17:12

AW: Trennung von Darstellung und Daten, Prinzipfrage konkret
 
Ich würde der „Datenklasse“ (unten „Item“) sowie der Klasse „Test“ einfach ein Event OnChanged respektive OnItemChanged (oder so ähnlich) verpassen. „Test“ registriert automatisch für alle seine Items den OnChanged-Handler, und leitet die dort „abgefangenen“ Events dann über OnItemChanged nach außen weiter.
Delphi-Quellcode:
type
  TItem = class
  protected
    FOnChanged: TNotifyEvent;
    procedure SetValue(const AValue: integer);
  public
    property Value: integer read FValue write SetValue;
    property OnChanged: TNotifyEvent read FOnChanged write FOnChanged;
  end;

  // Typensichere Objektliste, oder unter neueren Versionen TList<Item>
  TItemList = class(TObjectList) {&#8230;} end;

  TOnItemChanged = procedure (Sender: TObject; Item: TItem) of object;

  TTest = class
  protected
    FList: TItemList;
    FOnItemChanged: TOnItemChanged;
    procedure HandleItemChanged(Sender: TObject);
  public
    property OnItemChanged: TOnItemChanged read FOnItemChanged write FOnItemChanged;
    property List: TItemList read FList;
    procedure LoadData;
  end;

implementation

procedure TItem.SetValue(const AValue: integer);
begin
  FValue := AValue;
  if Assigned(OnChanged) then
    OnChanged(self);
end;

procedure TTest.HandleItemChanged(Sender: TObject);
begin
  { &#8230;eventuell noch selbst irgendwas tun?&#8230; }
  if Assigned(OnItemChanged) then
    OnItemChanged(self, Sender as TItem);
end;

procedure TTest.LoadData;
var
  i: integer;
  function MakeItem(Value: integer): TItem
  begin
    Result := TItem.Create;
    // wichtig:
    Result.OnChanged := HandleItemChanged;
    Result.Value := Value;
  end;
begin
  for i := 0 to 42 do
    FList.Add(MakeItem(i));
end;
Delphi-Quellcode:
type
  TMyForm = class(TForm)
    {&#8230;}
    Listview: TListView;
  protected
    FTest: TTest;
    procedure HandleItemChanged(Sender: TObject; Item: TItem);
  end;

implementation

procedure HandleItemChanged(Sender: TObject; Item: TItem);
begin
  { &#8230; Listview neuzeichnen (bzw. nur das jeweilige Item) &#8230; }
end;

procedure TMyForm.FormCreate({&#8230;})
begin
  FTest := TTest.Create;
  FTest.OnItemChanged := HandleItemChanged;
end;
Das Beispiel habe ich hier nur eben hier im Beitragseditor runtergeschrieben. Es gibt natürlich noch ein paar Dinge, die man in einer echten Anwendung sauberer lösen könnte/müsste (z.B. sollte TItemList irgendein Ereignis bereitstellen, wenn neue Items hinzugefügt werden, damit deren OnChanged-Handler gleich automatisch belegt werden kann), aber es geht hier ja nur um das grobe Prinzip...

Wenn das GUI an mehreren Stellen gleichzeitig aktualisiert werden muss, musst du statt Events das Observer-Pattern implementieren (*hust* deshalb wären Multicast-Events toll *hust*).


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:27 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz