ViewModelBase-Klasse
Basisklasse für ViewModels nach dem MVVM-Muster, mit einigen Vereinfachungen für abgeleitete Klassen.
Wahrscheinlich gibt es in jedem WPF-Projekt, das nach dem MVVM-Muster (Model–View–ViewModel) aufgebaut ist, irgendwo eine Klasse mit dem Namen „ViewModelBase“. Sie dient als Basisklasse für alle ViewModel-Klassen der Anwendung und stellt meist eine Implementierung der INotifyPropertyChanged
-Schnittstelle bereit. Im einfachsten Fall ist das neben dem Ereignis noch eine geschützte Methode wie „OnPropertyChanged“ oder auch „RaisePropertyChanged“.
Das allein macht dem Programmierer das Leben aber noch nicht einfacher, wenn in zahlreichen Klassen ebenso zahlreiche Eigenschaften implementiert werden, die noch dazu Abhängigkeiten untereinander besitzen (berechnete Eigenschaften).
Meine Implementierung dieser Klasse stellt die folgenden Vereinfachungen für WPF-Anwendungen bereit:
Manche Ideen sind von Steve Cadwallader übernommen, der eine ausführlichere Beschreibung in drei Artikeln bereitstellt (1, 2, 3).
Kompatibilität:
Diese Funktionalität mit noch weniger Schreibaufwand, voller Performance und geringerem Speicherverbrauch gibt es mit dem neueren Fody-Addin ViewModelKit.Fody.
Beispiel
Die folgende Beispielklasse zeigt eine Ableitung der ViewModelBase-Klasse:
{
#region Data properties
// Ersetzung der gemeinsamen DisplayName-Eigenschaft
public override string DisplayName
{
get { return Vorname + " " + Nachname; }
set { }
}
// Verwendung von GetValue und SetValue mit C# 4 (.NET 4.0, Visual Studio 2010)
public string Vorname
{
get { return GetValue<string>("Vorname"); }
set { SetValue(value, "Vorname"); }
}
// Verwendung von GetValue und SetValue mit C# 5 (.NET 4.5, Visual Studio 2012+)
public string Nachname
{
get { return GetValue<string>(); }
set { SetValue(value); }
}
// Änderungsmethode wird aufgerufen, wenn Nachname geändert wurde (nachdem der Wert
// gespeichert und bevor das PropertyChanged-Ereignis ausgelöst wird)
[PropertyChangedHandler("Nachname")]
private void OnNachnameChanged()
{
if (knownNames.Contains(Nachname))
{
SayHelloCommand.TryExecute();
}
}
// Neuformatierung eines Datums als Texteingabe;
// Änderung dieser Eigenschaft setzt IsModified auf true
[SetsModified]
public string Geburtsdatum
{
get { return GetValue<string>(); }
set { SetValue(SanitizeDate(value)); }
}
// Ändert sich mit Geburtsdatum
[NotifiesOn("Geburtsdatum")]
public int Alter
{
get
{
return (DateTime.Now - DateTime.Parse(Geburtsdatum)).Years; // Pseudocode!
}
}
#endregion Data properties
#region Commands
// Deklaration aller Commands;
// SayHello ist vom aktuellen Geburtsdatum abhängig
[NotifiesOn("Geburtsdatum")]
public DelegateCommand SayHelloCommand { get; private set; }
// Initialisierung der Commands, wird vom Konstruktor aufgerufen
protected override void InitializeCommands()
{
SayHelloCommand = new DelegateCommand(OnSayHello, CanSayHello);
}
// Command-Handler-Methoden
private bool CanSayHello()
{
return DateTime.Parse(Geburtsdatum) < DateTime.Now;
}
private void OnSayHello()
{
Console.WriteLine("Hallo " + DisplayName + "!");
}
#endregion Commands
}
Download
ViewModelBase.cs33,7 KiBQuelltext der ViewModelBase-Klasse
Hinweise zur Verwendung
Zur Verwendung der ViewModelBase-Klasse werden die CollectionDictionary-Klasse und die DelegateCommand-Klasse benötigt.
Je nachdem, ob die ViewModelBase-Klasse in einem Projekt für .NET 4.0 oder ab 4.5 eingesetzt wird, muss die Symboldefinition von CSHARP50
am Dateianfang aktiviert oder deaktiviert werden. Sie wird verwendet, um möglichst kompakten Code für beide Umgebungen zu schreiben, der das CallerMemberName
-Attribut verwendet.
Änderungen
IsModified
management with a predefined property, set totrue
whenever a property marked with theSetsModified
attribute is changed. Reset this in your code after loading and saving. TheDisplayName
property can be included by setting theDisplayNameSetsModified
property.ViewState
management with a dynamic object, much likeViewBag
in ASP.NET MVC. Lets you store and restore the current state of a view when navigating back and forth.- Dependent commands: Commands marked with the
NotifiesOn
attribute raise theirCanExecuteChanged
event when the specified property changes. (Requires theDelegateCommand
andCollectionDictionary
classes.) - Fix: Removed static reflection cache that may have caused memory leaks by keeping a reference to old ViewModel instances.
- Code cleanup (formatting).
Lizenz und Nutzungsbedingungen
Vervielfältigung und Weiterverbreitung dieser Datei, verändert oder unverändert, sind gestattet, vorausgesetzt die Urheberrechtsangabe und dieser Hinweis bleiben erhalten. Diese Datei wird wie vorliegend ohne jegliche Garantie oder Gewährleistung angeboten. (GNU All-Permissive-Lizenz)
Statistische Daten
- Erstellt am 2012-07-09, aktualisiert am 2015-08-27.
- Ca. 650 Codezeilen, geschätzte Entwicklungskosten: 650 - 2 600 €