WPF setzt quasi die Verwendung von Styles und DataTemplates voraus. Durch das Aufkommen des MVVM-Patterns werden viele Problematiken gerade über DataTemplates gelöst. Dadurch entstehen Vorlagen für Datentypen, die je nach Anwendungsfall für eine unterschiedliche Darstellung sorgen sollen. Gleiches gilt auch für Styles. Dafür sieht WPF Selektoren vor, die implementiert werden können, um die Wahl der richtigen Ressource einfacher zu gestalten. Doch wie werden sie verwendet?

Von Wichtigkeit sind zwei Basisklassen:

  • StyleSelector: Dient der Auswahl von Styles und stellt die Methode SelectStyle zur Verfügung, die überschrieben und damit an die eigenen Bedürfnisse hin angepasst werden kann.
  • DataTemplateSelector: Dient der Auswahl von Datenvorlagen und stellt die Methode SelectTemplate zur Verfügung.

Implementierung

In einem kleinen Beispiel wird eine Anwendung zur Anzeige von Personen erstellt. Diese bietet die Auswahl von Personen per ComboBox-Element als auch per ListBox an. Je nach Geschlecht der Person soll die Darstellung unterschiedlich erfolgen.

Da dieses Verhalten sowohl für den Container von List-Elementen (hier wird ein Style benötigt) als auch für Typen vom Typ ContentControl (hier wird ein DataTemplate benötigt) notwendig ist, werden Selektoren für beide Fälle implementiert.

Nachfolgend findet sich die Implementierung für den Style-Selektor. Dieser prüft ob das übergebene Objekt vom Typ Person ist und liefert je nach Geschlecht den Namen einer anderen Ressource zurück. Auf Basis dieses Namens wird die Resource gesucht und ein Style-Objekt nach aussen gegeben.

public class SexStyleSelector : StyleSelector
{
    public override System.Windows.Style SelectStyle(
        object item, 
        System.Windows.DependencyObject container)
    {
        Person p = item as Person;
        if (p != null)
        {
            string styleName = String.Empty;
            switch (p.Sex)
            {
                case Sex.None:
                    styleName = "DefaultSexStyle";
                    break;
                case Sex.Male:
                    styleName = "MaleSexStyle";
                    break;
                case Sex.Female:
                    styleName = "FemaleSexStyle";
                    break;
            }
            return Application.Current.TryFindResource(styleName) as Style;
        }
        return base.SelectStyle(item, container);
    }
}

Analog dazu wird der Vorlagen-Selektor implementiert:

public class SexTemplateSelector : DataTemplateSelector
{
    public override System.Windows.DataTemplate SelectTemplate(
        object item, 
        System.Windows.DependencyObject container)
    {
        Person p = item as Person;
        if (p != null)
        {
            string styleName = String.Empty;
            switch (p.Sex)
            {
                case Sex.None:
                    styleName = "DefaultSexTemplate";
                    break;
                case Sex.Male:
                    styleName = "MaleSexTemplate";
                    break;
                case Sex.Female:
                    styleName = "FemaleSexTemplate";
                    break;
            }
            return Application.Current.TryFindResource(styleName) as DataTemplate;
        }
        return base.SelectTemplate(item, container);
    }
}

Darstellung

Im Anschluss müssen die entsprechenden Styles und Vorlagen deklariert werden. Diese können aus dem angehängten File entnommen werden. Schlussendlich muss noch eine korrekte Einbindung in die Darstellung vorgenommen werden:

<StackPanel>
    <ComboBox ItemsSource="{Binding Path=People,Source={StaticResource DataMock}}"
                ItemContainerStyleSelector="{StaticResource SexStyleSelector}"
                ItemTemplateSelector="{StaticResource SexTemplateSelector}"
                Margin="10"
                />

    <ListBox ItemsSource="{Binding Path=People,Source={StaticResource DataMock}}"
                ItemContainerStyleSelector="{StaticResource SexStyleSelector}"
                Margin="10"
                />
</StackPanel>

Besonderes Augenmerk sollte hierbei auf die ComboBox gelegt werden. Diese enthält eine Area, welche die einzelnen Objekte darstellt. Jedes der Objekte wird in einem ComboBoxItem-Container dargestellt, der einen Style für die Darstellung benötigt. Damit aber auch der ausgewählte Eintrag wie gewollt dargestellt werden kann, muss die Eigenschaft ItemTemplateSelector mit dem gewünschten Selektor versehen werden, der das korrekte DataTemplate auswählt.

Resultat

image

Es ist also nicht viel Code notwendig, um eine derartige Aufgabe zu lösen, zumal dies sehr oft ohne die Möglichkeit der Selektoren implementiert wird und dadurch natürlich sehr schnell das MVVM-Pattern verletzt werden kann, oder – bei Nichtverwendung – Logik an Stellen zu finden ist, die dafür nicht geeignet sind.

Download

Download des Beispiels

Ü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.

2 Kommentare