AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Frage zum Designkonzept MVVM unter Delphi

Ein Thema von jus · begonnen am 20. Sep 2018 · letzter Beitrag vom 25. Sep 2018
Antwort Antwort
Seite 1 von 5  1 23     Letzte » 
jus

Registriert seit: 22. Jan 2005
344 Beiträge
 
Delphi 2007 Professional
 
#1

Frage zum Designkonzept MVVM unter Delphi

  Alt 20. Sep 2018, 12:19
Hallo,

ich beschäftige mit MVVM und komme da einfach nicht weiter. Und zwar würde ich gerne das folgende geniale Beispiel von Sir Rufo im Beitrag XE5: Probleme mit LiveBindings "CheckedState(Self)" weiter ausbauen, doch es scheitert bei mir bei den grundsätzlich Designfragen.

Was mache ich falsch?
Du benutzt Livebindings

Dafür nehme ich MVVM, das kann ich immer so hinbiegen wie ich möchte und bin nicht darauf angewiesen, ob Komponente X und Eigenschaft Y auch für Livebindings vorgesehen vorbereitet ist.
Delphi-Quellcode:
unit ViewFormMain;

interface

  uses
    Windows,
    Messages,
    SysUtils,
    Variants,
    Classes,
    Graphics,
    Controls,
    Forms,
    Dialogs,
    StdCtrls;

  type
    TViewModel = class
    private
      FValue : Boolean;
      FOnUpdate : TNotifyEvent;
      procedure SetValue( const Value : Boolean );
    protected
      procedure DoUpdate;
    public
      property OnUpdate : TNotifyEvent read FOnUpdate write FOnUpdate;
      property Value : Boolean read FValue write SetValue;
    end;

    TMainFormView = class( TForm )
      Edit1 : TEdit; // OI: OnChange => ControlChange
      Edit2 : TEdit; // OI: OnChange => ControlChange
      Edit3 : TEdit; // OI: OnChange => ControlChange
      CheckBox1 : TCheckBox; // OI: OnClick => ControlChange
      procedure ControlChange( Sender : TObject );
      procedure FormShow( Sender : TObject );
    private
      FModelLoading : Boolean;
      FViewModel : TViewModel;
    protected
      procedure DoLoadFromModel; virtual;
      procedure DoSaveToModel; virtual;
      procedure ViewModelUpdate( Sender : TObject );
    protected
      procedure LoadFromModel;
      procedure SaveToModel;
      procedure SyncWithModel;
    public
      procedure AfterConstruction; override;
      procedure BeforeDestruction; override;
      property ViewModel : TViewModel read FViewModel;
    end;

  var
    MainFormView : TMainFormView;

implementation

{$R *.dfm}
  { TForm1 }

  procedure TMainFormView.AfterConstruction;
    begin
      inherited;
      FViewModel := TViewModel.Create;
      FViewModel.OnUpdate := ViewModelUpdate;
    end;

  procedure TMainFormView.BeforeDestruction;
    begin
      inherited;
      FViewModel.Free;
    end;

  procedure TMainFormView.ControlChange( Sender : TObject );
    begin
      SyncWithModel;
    end;

  procedure TMainFormView.DoLoadFromModel;
    begin
      // Binding Model => View
      CheckBox1.Checked := ViewModel.Value;
      Edit1.Enabled := not ViewModel.Value;
      Edit2.Enabled := not ViewModel.Value;
      Edit3.Enabled := not ViewModel.Value;
    end;

  procedure TMainFormView.DoSaveToModel;
    begin
      // Binding View => Model
      ViewModel.Value := CheckBox1.Checked;
    end;

  procedure TMainFormView.FormShow( Sender : TObject );
    begin
      LoadFromModel;
    end;

  procedure TMainFormView.LoadFromModel;
    begin
      if FModelLoading
      then
        Exit;

      FModelLoading := True;
      try
        DoLoadFromModel;
      finally
        FModelLoading := False;
      end;
    end;

  procedure TMainFormView.SaveToModel;
    begin
      if FModelLoading
      then
        Exit;

      DoSaveToModel;
    end;

  procedure TMainFormView.SyncWithModel;
    begin
      SaveToModel;
      LoadFromModel;
    end;

  procedure TMainFormView.ViewModelUpdate( Sender : TObject );
    begin
      LoadFromModel;
    end;

  { TViewModel }

  procedure TViewModel.DoUpdate;
    begin
      if Assigned( OnUpdate )
      then
        OnUpdate( Self );
    end;

  procedure TViewModel.SetValue( const Value : Boolean );
    begin
      if Value = FValue
      then
        Exit;

      FValue := Value;
      DoUpdate;
    end;

end.
Und zwar würde mich brennend interessieren, wie man das obige Konzept um Buttons und einem VirtualStringTree erweitern kann. Sollten man z.B. das OnClick Event von einem Button direkt mit der "ControlChange" Funktion verdrahten oder im ViewModel eine seperate Funktion erstellen?

lg,
jus

Geändert von jus (20. Sep 2018 um 12:21 Uhr)
  Mit Zitat antworten Zitat
Lemmy

Registriert seit: 8. Jun 2002
Ort: Berglen
2.379 Beiträge
 
Delphi 10.3 Rio
 
#2

AW: Frage zum Designkonzept MVVM unter Delphi

  Alt 20. Sep 2018, 12:48
ist eigentlich ganz einfach:
was macht ControlChange? Es soll das Model/den Inhalt der Oberfläche aktualisieren.

Frage: Was soll beim Click auf den Button passieren? das selbe? Dann klar, mit der Methode verbinden. Wenn es was anderes machen soll, dann eben mit einer anderen Methode...

Vielleicht wird es mit einer Gegenfrage deutlicher: Du hast nicht nur einen Button, sondern 2. Soll jetzt bei einem Click auf einen der beiden Buttons immer das selbe passieren oder unterschiedliche Sachen?
  Mit Zitat antworten Zitat
jus

Registriert seit: 22. Jan 2005
344 Beiträge
 
Delphi 2007 Professional
 
#3

AW: Frage zum Designkonzept MVVM unter Delphi

  Alt 20. Sep 2018, 23:55
Hallo Lemmy,
prinzipiell war meine erste Überlegung auch, dass ich einfach eine neue ViewModel-Methode erstelle. Um die kommt man vermutlich eh nicht rum. Was ich meine ist aber, dass das geniale an Sir Rufos Code ist, dass er die ganzen OnChange Events in ControlChange zusammenfaßt hat und die dann zentral auswertet. Ich versuche es kurz mal mit Code zu erklären. Und zwar weiß ich nicht, ob ich bei einem Button entweder sowas mache wie:
Delphi-Quellcode:
unit ViewFormMain;

interface
//...

  type
    TViewModel = class
    private
      FValue : Boolean;
      FOnUpdate : TNotifyEvent;
      procedure SetValue( const Value : Boolean );
    protected
      procedure DoUpdate;
    public
      procedure Button1Click;
      property OnUpdate : TNotifyEvent read FOnUpdate write FOnUpdate;
      property Value : Boolean read FValue write SetValue;
    end;

//...
implementation
//...


procedure TMainFormView.Button1Click(Sender: TObject);
begin
  ViewModel.Button1Click;
end;

 procedure TViewModel.Button1Click;
    begin
      //tue irgendwas
      showmessage('Mach Beep!');
    end;
Oder auch den OnClick Event vom Button1 direkt mit ControlChange verdrahte, und dann erst später die Verzweigung zu TViewModel.Button1Click mache, und zwar ungefähr so:
Delphi-Quellcode:
unit ViewFormMain;

interface
//...

  type
    TViewModel = class
    private
      FValue : Boolean;
      FOnUpdate : TNotifyEvent;
      procedure SetValue( const Value : Boolean );
    protected
      procedure DoUpdate;
    public
      procedure Button1Click;
      property OnUpdate : TNotifyEvent read FOnUpdate write FOnUpdate;
      property Value : Boolean read FValue write SetValue;
    end;

//...
implementation
//...

  procedure TMainFormView.DoSaveToModel( Sender : TObject );
    begin
      // Binding View => Model
      ViewModel.Value := CheckBox1.Checked;
      if (Sender as TComponent).Name = 'Button1then ViewModel.Button1Click;
    end;



 procedure TViewModel.Button1Click;
    begin
      //tue irgendwas
      showmessage('Mach Beep!');
    end;
Hmmm... da weiss ich halt nicht wie Sir Rufo das gelöst hätte?

Geändert von jus (20. Sep 2018 um 23:58 Uhr)
  Mit Zitat antworten Zitat
freimatz

Registriert seit: 20. Mai 2010
1.440 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Frage zum Designkonzept MVVM unter Delphi

  Alt 21. Sep 2018, 08:14
Hallo Lemmy,
prinzipiell war meine erste Überlegung auch, dass ich einfach eine neue ViewModel-Methode erstelle. Um die kommt man vermutlich eh nicht rum. Was ich meine ist aber, dass das geniale an Sir Rufos Code ist, dass er die ganzen OnChange Events in ControlChange zusammenfaßt hat und die dann zentral auswertet.
[...]
Hmmm... da weiss ich halt nicht wie Sir Rufo das gelöst hätte?
Ist das wichtig? Es ist doch dein code
Für zwei Aktionen die was verschiedenes machen brauchst Du nun mal auch im viewmodel zwei Dinge. Das könnte auch eine Methode mit einem Parameter sein. Oder zwei Klassen.

Auch wenn es dir nicht weiter hilft: Wir haben uns was selbst gestrickt und da erfolgt in so einem Fall das Binding von je einem Button auf je ein ViewCommand-Object im ViewModel.
  Mit Zitat antworten Zitat
Lemmy

Registriert seit: 8. Jun 2002
Ort: Berglen
2.379 Beiträge
 
Delphi 10.3 Rio
 
#5

AW: Frage zum Designkonzept MVVM unter Delphi

  Alt 21. Sep 2018, 09:38

Oder auch den OnClick Event vom Button1 direkt mit ControlChange verdrahte, und dann erst später die Verzweigung zu TViewModel.Button1Click mache, und zwar ungefähr so:
ich führ dein Beispiel mal fort..

Delphi-Quellcode:

  procedure TMainFormView.DoSaveToModel( Sender : TObject );
    begin
      // Binding View => Model
      ViewModel.Value := CheckBox1.Checked;
      if (Sender as TComponent).Name = 'Button1then ViewModel.Button1Click;
      if (Sender as TComponent).Name = 'Button2then ViewModel.Button2Click;
      if (Sender as TComponent).Name = 'Button3then ViewModel.Button3Click;
      if (Sender as TComponent).Name = 'Button4then ViewModel.Button4Click;
      if (Sender as TComponent).Name = 'Button5then ViewModel.Button5Click;
      if (Sender as TComponent).Name = 'Button6then ViewModel.Button6Click;
....
      if (Sender as TComponent).Name = 'Buttonnthen ViewModel.ButtonnClick;
 
    end;
Das willst Du machen? Echt? DoSaveToModel hat eine Aufgabe: Daten von der Gui in die Objekte zu speichern, aber sicher nicht zu schauen ob der Sender einen bestimmten Namen trägt um dann irgend was zu tun...



Ist das wichtig? Es ist doch dein code
ne, ist er nicht. Das ist der Code von dem Typ der nach ihm den Code warten muss. Wäre schön, wenn man immer wieder mal daran denkt...
  Mit Zitat antworten Zitat
freimatz

Registriert seit: 20. Mai 2010
1.440 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Frage zum Designkonzept MVVM unter Delphi

  Alt 21. Sep 2018, 11:11
Vielleicht wäre auch mal wichtig die Frage zu stellen: was willst Du mit MVVM erreichen? Entkoppelung? Testbarkeit? Views austauschen? Oder?
Je nach dem kann das Design anders aussehen.
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
4.064 Beiträge
 
Delphi 12 Athens
 
#7

AW: Frage zum Designkonzept MVVM unter Delphi

  Alt 21. Sep 2018, 12:00
Bin nicht sicher ob ich deine Frage richtig verstehe.
Aber ich denke das ViewModel ist ein Abbild des Views, und die Load/Save Routinen speichern das nur entsprechend ab zur Synchronisation der Beiden.

Delphi-Quellcode:
procedure TMainFormView.DoLoadFromModel;
begin
      // Binding Model => View
      CheckBox1.Checked := ViewModel.CheckBox1Checked;
      Edit1.Text := ViewModel.Edit1Text;
      Edit2.Text := ViewModel.Edit2Text;
      Edit3.Text := ViewModel.Edit2Text;
end;

...

procedure TMainFormView.DoSaveToModel;
begin
      // Binding View => Model
      ViewModel.CheckBox1Checked := CheckBox1.Checked;
      ViewModel.Edit1Text := Edit1.Text;
      ViewModel.Edit2Text := Edit2.Text;
      ViewModel.Edit3Text := Edit3.Text;
end;
so das die ganze Logik im Model ist, und nicht mehr im View.
Jeder Zugriff in die Logik passiert dann ausschliesslich über das Model.

Rollo
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.016 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#8

AW: Frage zum Designkonzept MVVM unter Delphi

  Alt 21. Sep 2018, 12:49
Brrrr, das ist doch kein MVVM, was Sir Rufo da geschrieben hat. Viel zu viel Code in der View.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
Schokohase
(Gast)

n/a Beiträge
 
#9

AW: Frage zum Designkonzept MVVM unter Delphi

  Alt 21. Sep 2018, 13:32
Ich habe mir schon so das ein oder andere zum Thema MVVM und Delphi angesehen. Dabei ging die Bandbreite von „lächerlich“ bis zu „ganz niedlich“ verglichen mit WPF, UWP, Xamarin.Forms mal als Referenz für „sehr brauchbar“.

Oder kennt jemand eine Delphi-Variante die sich mit der Referenz ansatzweise messen könnte?
  Mit Zitat antworten Zitat
freimatz

Registriert seit: 20. Mai 2010
1.440 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: Frage zum Designkonzept MVVM unter Delphi

  Alt 21. Sep 2018, 13:40
Brrrr, das ist doch kein MVVM, was Sir Rufo da geschrieben hat. Viel zu viel Code in der View.
Das kommt drauf an, was man unter MVVM versteht. Für mich gibt es (u.a.) zwei Sichtweisen die sich teilweise wiedersprechen.

1. Das Viewmodel abstrahiert die Daten und die Darstellung. Die View soll jederzeit austauschbar sein.
Beispiel: Es gibt ein Passwort und die Aktion Verbinden. Eine Logik besagt: die Aktion Verbinden darf nur ausgeführt werden, wenn das Passwort da ist.

2. Das Viewmodel repräsentiert die View, diese soll möglichst keine Logik enthalten.
Beispiel wie oben: Die Logik besagt: der Button für Verbinden ist nur Enabled, wenn in der Eingabe ein Text drin steht.

Bei 1 geht es eher um eine abstrakte Sichtweise, dagegen hat 2 eher die UI im Blick.

Anderes Beispiel:
Im Model hatten wir vier Auswahlmöglichkeiten. Es ging um die Plazierung einer gewissen Zone bezüglich der Oberfläche. Codiert ware das durch einen Aufzählungstyp.
Einerseits konnten wir das lösen mit einer IViewSelection im Viewmodel und in der UI einer Auswahlliste.
Andererseits war der Wunsch in der UI stattdessen vier Buttons zu haben (Radiobuttons waren auch eine Option)
Nach obiger Variante 2 würde man im Viewmodel dann vier IViewButtons machen und das Viewmodel schaut dass dann immer einer gedrückt ist.
Dagegen nach Variante 1 würde man bei der IViewSelection bleiben - es ist ja eine Auswahl - und dann in der UI die Logik implementieren.

Ich persönlich (und Stevie wphl auch) tendiere generell zu Variante 2. Da kann man mehr unit testen.

Ich habe mir schon so das ein oder andere zum Thema MVVM und Delphi angesehen. Dabei ging die Bandbreite von „lächerlich“ bis zu „ganz niedlich“ verglichen mit WPF, UWP, Xamarin.Forms mal als Referenz für „sehr brauchbar“.

Oder kennt jemand eine Delphi-Variante die sich mit der Referenz ansatzweise messen könnte?
Unsere
Betonung liegt allerdings auf "ansatzweise"

Geändert von freimatz (21. Sep 2018 um 13:43 Uhr)
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:55 Uhr.
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