Lose Kommunikation zwischen ViewModels an Hand eines Beispiels und verwendbarem Framework. Teil 2.

Relevante Artikel:

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.

Download WPF Messaging Demo

Auch dieses Mal freue ich mich wieder über alle Anregungen und Verbesserungsvorschläge.

Über den Autor

Norbert Eder

Ich bin ein leidenschaftlicher Softwareentwickler und Fotograf. Mein Wissen und meine Gedanken teile ich nicht nur hier im Blog, sondern auch in Fachartikeln und Büchern.

3 Kommentare

  • 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 :-)