|
![]() |
|
Registriert seit: 5. Jan 2005 Ort: Stadthagen 9.454 Beiträge Delphi 10 Seattle Enterprise |
#1
Im Anhang ist eine kleine Demo-Anwendnung
dp_178847.PNG Alle Elemente sind sehr lose gekoppelt und tauschen sich nur über Nachrichten aus. Die ausgetauschten Nachrichten lasse ich hier auf der rechten Seite anzeigen. Da die grundlegenden Units zum Messenger/ViewModel/Model etc. zwar schon sehr weit fortgeschritten aber noch nicht komplett fertig sind, gibt es im Moment nur den Code der konkreten Ableitungen.
Delphi-Quellcode:
unit Model.DemoData;
interface uses MVVM.Model; type TDemoDataModel = class( TModel ) private FStr : string; FInt : Integer; procedure SetStr( const Value : string ); procedure SetInt( const Value : Integer ); public property Str : string read FStr write SetStr; property Int : Integer read FInt write SetInt; end; implementation { TDemoDataModel } procedure TDemoDataModel.SetInt( const Value : Integer ); begin // SetField<T>( var Field : T; const Value : T; const PropName : string ) // Setzt den Wert der Variablen und schickt eine Nachricht, wenn sich der Wert geändert hat SetField<Integer>( FInt, Value, 'Int' ); end; procedure TDemoDataModel.SetStr( const Value : string ); begin SetField<string>( FStr, Value, 'Str' ); end; end.
Delphi-Quellcode:
unit ViewModel.Main;
interface uses MVVM.ViewModel, MVVM.Messenger.Messages, Model.DemoData; type TMainViewModel = class( TViewModel ) private FCurrentPageIndex : Integer; FData : TDemoDataModel; procedure SetCurrentPageIndex( const Value : Integer ); protected procedure MsgPropertyChanged( const AMessage : TPropertyChangedMessage ); override; public procedure AfterConstruction; override; procedure BeforeDestruction; override; property CurrentPageIndex : Integer read FCurrentPageIndex write SetCurrentPageIndex; property Data : TDemoDataModel read FData; end; implementation { TMainViewModel } procedure TMainViewModel.AfterConstruction; begin inherited; FData := TDemoDataModel.Create; end; procedure TMainViewModel.BeforeDestruction; begin inherited; FData.Free; end; procedure TMainViewModel.MsgPropertyChanged( const AMessage : TPropertyChangedMessage ); begin inherited; if AMessage.Sender = FData then DoNotify( 'Data.' + AMessage.PropName ); end; procedure TMainViewModel.SetCurrentPageIndex( const Value : Integer ); begin SetField<Integer>( FCurrentPageIndex, Value, 'CurrentPageIndex' ); end; end.
Delphi-Quellcode:
unit ViewForm.Main;
interface uses MVVM.Messenger.Messages, MVVM.ViewModel, ViewModel.Main, Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, ViewForm, Vcl.ComCtrls, Vcl.StdCtrls, Vcl.ExtCtrls; type TMainFormView = class( TFormView ) PageControl1 : TPageControl; ListBox1 : TListBox; Panel1 : TPanel; AddView_Button : TButton; GroupBox1 : TGroupBox; Panel2 : TPanel; GroupBox2 : TGroupBox; Edit1 : TEdit; ComboBox1 : TComboBox; procedure AddView_ButtonClick( Sender : TObject ); private FViewModel : TMainViewModel; procedure AddPageView; protected procedure MsgPropertyChanged( const AMessage : TPropertyChangedMessage ); override; procedure DoLoadFromModel; override; procedure DoSaveToModel; override; procedure DoGetViewModel( var ViewModel : TViewModel ); override; public procedure AfterConstruction; override; procedure BeforeDestruction; override; end; var MainFormView : TMainFormView; implementation {$R *.dfm} { TMainFormView } procedure TMainFormView.AddPageView; var LViewClass : TPersistentClass; LView : TFormView; begin // Die konkrete Klasse TDataEditFormView ist nicht bekannt (keine Abhängigkeiten=lose Koppelung) // darum wird die über einen Alias gesucht LViewClass := FindClass( 'DataEditView' ); if LViewClass.InheritsFrom( TFormView ) then begin LView := TFormClass( LViewClass ).Create( Self ) as TFormView; // Verdrahtung der ViewModels LView.ViewModel.Parent := FViewModel; // ab ins PageControl LView.ManualDock( PageControl1 ); LView.Align := alClient; // und anzeigen LView.Show; end; end; procedure TMainFormView.AddView_ButtonClick( Sender : TObject ); begin inherited; AddPageView; end; procedure TMainFormView.AfterConstruction; var LView : TFormView; begin inherited; FViewModel := TMainViewModel.Create; // Eine View packen wir schon mal hinzu AddPageView; // Setze ich normalerweise im OI (Bequemlichkeit) PageControl1.OnChange := ControlChange; Edit1.OnChange := ControlChange; ComboBox1.OnChange := ControlChange; end; procedure TMainFormView.BeforeDestruction; begin inherited; FreeAndNil( FViewModel ); end; procedure TMainFormView.DoGetViewModel( var ViewModel : TViewModel ); begin inherited; ViewModel := FViewModel; end; procedure TMainFormView.DoLoadFromModel; begin inherited; PageControl1.ActivePageIndex := FViewModel.CurrentPageIndex; Edit1.Text := FViewModel.Data.Str; ComboBox1.ItemIndex := FViewModel.Data.Int; end; procedure TMainFormView.DoSaveToModel; begin inherited; FViewModel.CurrentPageIndex := PageControl1.ActivePageIndex; FViewModel.Data.Str := Edit1.Text; FViewModel.Data.Int := ComboBox1.ItemIndex; end; procedure TMainFormView.MsgPropertyChanged( const AMessage : TPropertyChangedMessage ); begin inherited; ListBox1.ItemIndex := ListBox1.Items.Add( Format( '%s(%x).%s', [AMessage.Sender.ClassName, Integer( AMessage.Sender ), AMessage.PropName] ) ); end; end.
Delphi-Quellcode:
unit ViewModel.DataEdit;
interface uses MVVM.ViewModel, MVVM.Messenger.Messages; type TDataEditViewModel = class( TViewModel ) private function GetStr : string; procedure SetStr( const Value : string ); function GetInt : Integer; procedure SetInt( const Value : Integer ); protected procedure MsgPropertyChanged( const AMessage : TPropertyChangedMessage ); override; public property Str : string read GetStr write SetStr; property Int : Integer read GetInt write SetInt; end; implementation uses System.StrUtils, ViewModel.Main; { TDataEditViewModel } function TDataEditViewModel.GetInt : Integer; begin if Parent is TMainViewModel then Result := ( Parent as TMainViewModel ).Data.Int else Result := -1; end; function TDataEditViewModel.GetStr : string; begin if Parent is TMainViewModel then Result := ( Parent as TMainViewModel ).Data.Str else Result := ''; end; procedure TDataEditViewModel.MsgPropertyChanged( const AMessage : TPropertyChangedMessage ); begin inherited; if AMessage.Sender = Parent then case IndexText( AMessage.PropName, ['Data.Str', 'Data.Int'] ) of 0 : DoNotify( 'Str' ); 1 : DoNotify( 'Int' ); end; end; procedure TDataEditViewModel.SetInt( const Value : Integer ); begin if Parent is TMainViewModel then ( Parent as TMainViewModel ).Data.Int := Value; end; procedure TDataEditViewModel.SetStr( const Value : string ); begin if Parent is TMainViewModel then ( Parent as TMainViewModel ).Data.Str := Value; end; end.
Delphi-Quellcode:
Nachtrag
unit ViewForm.DataEdit;
interface uses MVVM.ViewModel, MVVM.Messenger.Messages, ViewModel.DataEdit, Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, ViewForm, Vcl.StdCtrls; type TDataEditFormView = class( TFormView ) ListBox1 : TListBox; Edit1 : TEdit; private FViewModel : TDataEditViewModel; protected procedure DoLoadFromModel; override; procedure DoSaveToModel; override; procedure DoGetViewModel( var ViewModel : TViewModel ); override; public procedure AfterConstruction; override; procedure BeforeDestruction; override; end; var DataEditFormView : TDataEditFormView; implementation {$R *.dfm} { TDataEditFormView } procedure TDataEditFormView.AfterConstruction; begin inherited; FViewModel := TDataEditViewModel.Create; ListBox1.OnClick := ControlChange; Edit1.OnChange := ControlChange; end; procedure TDataEditFormView.BeforeDestruction; begin inherited; FViewModel.Free; end; procedure TDataEditFormView.DoGetViewModel( var ViewModel : TViewModel ); begin inherited; ViewModel := FViewModel; end; procedure TDataEditFormView.DoLoadFromModel; begin inherited; ListBox1.ItemIndex := FViewModel.Int; Edit1.Text := FViewModel.Str; end; procedure TDataEditFormView.DoSaveToModel; begin inherited; FViewModel.Int := ListBox1.ItemIndex; FViewModel.Str := Edit1.Text; end; initialization RegisterClassAlias( TDataEditFormView, 'DataEditView' ); end. Zum Verständnis: In TFormView ist definiert, dass bei einer Änderung des zugehörigen ViewModels automatisch LoadFromModel aufgerufen wird. (hier konkret in einer LazyLoadFromModel, wo erst 100ms nach der letzen Änderung das Laden erfolgt - das kann man sehr schön sehen, wenn man im Edit-Feld eine Taste gedrückt lässt)
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 (31. Jan 2014 um 12:07 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 |
![]() |
![]() |