|
Registriert seit: 5. Jan 2005 Ort: Stadthagen 9.454 Beiträge Delphi 10 Seattle Enterprise |
#2
Das ist irgendwie kein MVC, sondern irgendwas ... Nur weil man da etwas Model-View-Controller benennt, wird es noch kein MVC.
Schau dir mal an wie bei apple mit MVC gearbeitet wird, dann bekommt man eine ungefähre Vorstellung. Da hat der Controller jedes Control auf der View und auch da wird das erst benannt.
Delphi-Quellcode:
Problematisch ist und bleibt aber das vernünftige Umsetzen. Um es richtig zu machen müsste der Controller die Controls erzeugen und die View müsste sich nur noch merken an welcher Stelle diese Controls dargestellt werden sollen. Wenn das gesamte Framework dafür vorbereitet ist, dann ist alles ganz einfach. Wenn nicht, dann fängt man quasi bei Adam und Eva an.
TViewController = class
public property Firstname : TEdit; property Lastname : TEdit; end; TView = class( TForm ) Edit1 : TEdit; // -> ViewController.Firstname Edit2 : TEdit; // -> ViewController.Lastname end; Da ist das MVVM schon "wesentlich einfacher" umzusetzen und kommt deinem Entwurf auch wesentlich näher. Grundlegend bei den Entwürfen ist aber, dass die Views nicht die ViewModels/Controller erzeugen, denn sonst geht der gesamte Vorteil der Testbarkeit sofort flöten und die Views übernehmen auf einmal wieder die Kontrolle. Ich kann dir mal ein kleines Beispiel zeigen, wie ich das mit MVVM mache:
Genauso wie das ActivityViewModel der ActivityView zugewiesen wird. Im Anhang habe ich den gesamten restlichen Source (exclusive den Basis-Units) und die ausführbare Exe angehängt Zum besseren Verständnis hier einmal die BaseView
Delphi-Quellcode:
und natürlich die ViewModelBase
unit MVVM.View.FMX.Form.Base;
interface uses de.itnets.Events, de.itnets.References, MVVM.Core, MVVM.ViewModel.ViewModelBase, System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs; type TViewBaseForm = class( TForm, IView ) private FViewModel: WeakRef<TViewModelBase>; function GetViewModel: TViewModelBase; protected procedure ViewModelPropertyChanged( Sender: TObject; const e: TPropertyChangedArgs ); virtual; procedure AttachToViewModel( AViewModel: TViewModelBase ); virtual; procedure DetachFromViewModel( AViewModel: TViewModelBase ); virtual; public procedure SetViewModel( AViewModel: TViewModelBase ); virtual; procedure BeforeDestruction; override; function Equals( Obj: TObject ): Boolean; override; end; var ViewBaseForm: TViewBaseForm; implementation {$R *.fmx} { TForm1 } procedure TViewBaseForm.AttachToViewModel( AViewModel: TViewModelBase ); begin AViewModel.PropertyChanged.Add( Self.ViewModelPropertyChanged ); end; procedure TViewBaseForm.BeforeDestruction; begin SetViewModel( nil ); inherited; end; procedure TViewBaseForm.DetachFromViewModel( AViewModel: TViewModelBase ); begin AViewModel.PropertyChanged.Remove( Self.ViewModelPropertyChanged ); end; function TViewBaseForm.Equals( Obj: TObject ): Boolean; begin Result := ( Self = Obj ) or Assigned( Obj ) and {} ( ( Obj is TViewBaseForm ) and ( Self.FViewModel = ( Obj as TViewBaseForm ).FViewModel ) ) {} or {} ( Self.FViewModel.IsAssigned and Self.FViewModel.Reference.Equals( Obj ) ); end; function TViewBaseForm.GetViewModel: TViewModelBase; begin Result := FViewModel; end; procedure TViewBaseForm.SetViewModel( AViewModel: TViewModelBase ); begin if FViewModel <> AViewModel then begin if FViewModel.IsAssigned then DetachFromViewModel( FViewModel ); FViewModel := AViewModel; if FViewModel.IsAssigned and not( csDestroying in Self.ComponentState ) then begin AttachToViewModel( FViewModel ); PropertyChangedEvent.Call( ViewModelPropertyChanged, FViewModel, TPropertyChangedArgs.Create( ) ); end; end; end; procedure TViewBaseForm.ViewModelPropertyChanged( Sender: TObject; const e: TPropertyChangedArgs ); begin // Nothing to do here end; end.
Delphi-Quellcode:
PS Ein für mich sehr wichtiger Punkt ist die Unterstützung von allen Plattformen mit so wenig Anpassungen wie möglich. Dieser Code läuft ohne Änderungen exakt gleich auf Windows, OSX und Android (iOS nicht getestet, aber da befürchte ich eigentlich keine großen Überraschungen)
unit MVVM.ViewModel.ViewModelBase;
interface uses de.itnets.Events, de.itnets.References; type TViewModelBase = class private FPropertyChanged: PropertyChangedEvent; FDisplayName: string; function GetPropertyChanged: IPropertyChangedEvent; protected procedure SetDisplayName( const Value: string ); procedure OnPropertyChanged( const PropertyName: string = '' ); overload; procedure OnPropertyChanged( const PropertyNames: TArray<string> ); overload; public property DisplayName: string read FDisplayName; property PropertyChanged: IPropertyChangedEvent read GetPropertyChanged; end; TViewModelClass = class of TViewModelBase; implementation { TViewModel } function TViewModelBase.GetPropertyChanged: IPropertyChangedEvent; begin Result := FPropertyChanged; end; procedure TViewModelBase.OnPropertyChanged( const PropertyNames: TArray<string> ); var LPropertyName: string; begin for LPropertyName in PropertyNames do begin OnPropertyChanged( LPropertyName ); end; end; procedure TViewModelBase.OnPropertyChanged( const PropertyName: string ); begin FPropertyChanged.Invoke( Self, TPropertyChangedArgs.Create( PropertyName ) ); end; procedure TViewModelBase.SetDisplayName( const Value: string ); begin if FDisplayName <> Value then begin FDisplayName := Value; OnPropertyChanged( 'DisplayName' ); end; end; end.
Kaum macht man's richtig - schon funktioniert's
![]() Zertifikat: Sir Rufo (Fingerprint: ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60) Geändert von Sir Rufo ( 5. Feb 2015 um 12:43 Uhr) |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs 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
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |