Relevante Artikel:
- Lose Kommunikation zwischen ViewModels
- Lose Kommunikation zwischen ViewModels – Teil 2
- Binden von ViewModels via Locator
In den vorangegangenen Teilen (sowohl zum Thema Lose Kommunikation zwischen ViewModels als auch dem Binden von ViewModels über einen Locator) habe ich eine beispielhafte Implementierung bereit gestellt.
Nach der ersten Implementierung und einigen Anpassungen habe ich das resultierende Mini-Framework in eine vorhandene Anwendung integriert und bin dabei auf ein kleineres Problem gestoßen. Dieses bestand darin, dass die vorgestellte Lösung des Locators ein Binding an ein ViewModel ausschließlich über XAML unterstützt hat. Um zur Laufzeit für einen Bereich das ViewModel (und per DataTemplate
die dazugehörige View) zu wechseln musste eine eigene Instanz des Locators erstellt werden. Dies ist nicht gewollt, da alles über denselben Locator laufen soll, um unnötige Instanzen und damit ungewollte Verhalten zu vermeiden.
Aus diesem Grund musste das Design leicht verändert und angepasst werden. Neu hinzugekommen ist eine statische Klasse ObjectLocator
.
public static class ObjectLocator
{
private static ILocator locator = new ViewModelLocator();
public static ILocator Current
{
get
{
return locator;
}
}
public static void Register(ILocator locatorToRegister)
{
if (locatorToRegister == null)
throw new ArgumentNullException("locatorToRegister");
locator = locatorToRegister;
}
}
Diese Klasse bietet über die Eigenschaft Current
einen Default-Locator an, der durch eine Instanz der Klasse ViewModelLocator
bereit gestellt wird. Über die Methode Register
kann ein benutzerdefinierter Locator am ObjectLocator
angemeldet werden. Die Klasse ViewModelLocator
selbst ist nun internal
. Durch die Implementierung des Interfaces ILocator
kann ein benutzerdefinierter Locator erstellt und registriert werden.
Von der Handhabung hat sich nicht viel geändert. Bisher wurde über die Anwendungs-Ressourcen eine Instanz der Klasse ViewModelLocator
zur Verfügung gestellt. Dies hat sich dahingehend geändert, dass ab sofort über einen ObjectDataProvider der statische ObjectLocator
angeboten wird.
<ObjectDataProvider x:Key="Locator"
ObjectInstance="{x:Static loc:ObjectLocator.Current}"/>
In einer View kann nun per folgendem Markup der Datenkontext gesetzt werden:
<StackPanel DataContext="{Binding [FirstViewModel], Source={StaticResource Locator}}">
...
</StackPanel>
Auch kann per Sourcecode auf dieselbe Instanz des registrierten Locators per
ObjectLocator.Current.GetInstance("RegisteredViewModelName")
zugegriffen werden.
Die Implementierung, ein Beispiel und Unit Tests sind wie gewohnt angehängt.
Auch dieses Mal freue ich mich wieder über alle Anregungen und Verbesserungsvorschläge.
Hallo Norbert,
erstmal echt cool Artikel dieser Art zu finden. Aber ich habe einen Kritikpunkt, der vielleicht interessant für dich ist: Mir fehlen die Kommentare im Quellcode.
Ich muss mich tagtäglich mit endlosen Zeilen in diversen skurrilen Klassen auseinandersetzen und werde immer sauer, wenn ich keine Kommentare finde. Meiner Erfahrung nach ist das lesen eines “fremden” Quellcodes bei weitem einfacher und schneller. Und, ich kann mich innerhalb vieler Zeilen schneller auf das Wesentliche Konzentrieren.
Mir selber wird mein eigener Quellcode um die Ohren gehauen, wenn ich nicht Kommentiere, und ich weiß es mittlerweile zu schätzen. Aber trotz allen, schöne Artikel.
Gruß und dranbleiben :-)
Hallo Herr Eder,
leider kann ich den Anhang mit dem Code nicht finden.
Hallo, der Anhang ist nun wieder verfügbar. Vielen Dank für die Info.