C#/XAML: Binding mit mehreren Properties

Wer unter Visual Studio mit C# programmiert und WPF-Projekte bearbeitet, kommt ums Binding innerhalb der XAML-Dateien nicht drumherum. Binding ist auch eine feine, praktische Sache, doch stellt es einen auch immer wieder vor Hürden und scheint oftmals erstmal aufwendiger als CodeBehind zu benutzen. Eine Problemstellung ist, wenn man ein Binding mit mehreren Properties machen möchte. Das heißt man möchte verschiedene Eigenschaften an ein Element oder eine Element-Eigenschaft binden.

Nehmen wir als Beispiel eine Textbox und deren Eigenschaft “IsEnabled“. Ob die Textbox “enabled” ist, soll mehreren anderen UI-Elementen abhängen. Und zwar einmal davon, ob in einem GridView mindestens 1 Eintrag vorhanden ist oder ob eine von zwei Checkboxen angewählt ist.

ViewModel

Die Einträge des GridView werden im ViewModel als eine ObservableCollection repräsentiert. Und die Checkboxes sind im ViewModel an zwei boolsche Werte (CheckWeekMo und CheckWeekTue) gebunden.

public bool CheckWeekMo
{
    get => _checkWeekMo;
    set => Set(() => CheckWeekMo, ref _checkWeekMo, value);
}
public bool CheckWeekTue
{
    get => _checkWeekTue;
    set => Set(() => CheckWeekTue, ref _checkWeekTue, value);
}

public ObservableCollection<MyObject> CalendarExceptionDates
{
    get => _calendarExceptionDates;
    set => Set(() => CalendarExceptionDates, ref _calendarExceptionDates, value);
}

Zum Verständnis: Falls jemanden die Properties etwas ungewöhnlich erscheinen. Hier wurde die GalaSoft.MvvMLight-Bibliothek verwendet für eine Vereinfachung der PropertyChanged-Anweisung.

Multibinding in XAML-Datei

Nun sollen diese Eigenschaften auch darüber entscheiden, ob eine Textbox enabled oder disabled ist. Dazu nutzt man in der XAML-Datei das Multibinding. Das sieht dann wie folgt aus:

<TextBox x:Name="TextMyText" Text="{Binding SomeText}"
    MinWidth="180" HorizontalAlignment="Left" Margin="2,2,2,2" Height="Auto">
    <TextBox.IsEnabled>
        <MultiBinding Converter="{StaticResource EnableConverter}">
            <Binding Path="CalendarExceptionDates.Count"/>
            <Binding Path="CheckWeekMo"/>
            <Binding Path="CheckWeekTue"/>
        </MultiBinding>
    </TextBox.IsEnabled>
</TextBox>

Von der ObersavableCollection übergeben wir hier das Property Count, weil wir ja wissen möchten, ob das GridView mindestens einen Eintrag enthält.

Wie man sieht benötigt man in diesem Fall einen Converter, der aus einer gewünschten Kombination dieser Eigenschaften true oder false zurückgibt, um die Textbox zu aktivieren oder eben zu deaktivieren. Der Konverter muss auch noch in den Resourcen der xaml-Datei definiert werden.

<Window.Resources>
    <local:EnableConverter x:Key="EnableConverter"/>
</Window.Resources>

Converter-Klasse

Jetzt muss man nur noch die passende Converter-Class erstellen. In unserem Beispiel heißt die Klasse “EnableConverter“. Diese Klasse erbt Ihre Methoden von der Interface-Klasse IMultiValueConverter bzw. muss deren Methoden-Definitionen implementieren.

Die einzelnen Properties werden in der Convert-Methode als object[]-Array übergeben. Beim Zugriff auf das jeweilige Element im Array muss man diesen dann in den jeweiligen Datentyp konvertieren. Die Reihenfolge der Properties in dem Array entspricht genau der, wie sie im MultiBinding in der XAML-Datei definiert ist. Gibt es hier Abweichungen, so führt das zu einem Fehler in der Ausführung.

public class EnableConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        int i = (int)values[0];
        bool mo = (bool)values[1];
        bool tu = (bool)values[2];
        if ((i > 0) || mo || tu)
        {
            return true;
        }
        else
        {
                return false;
        }
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        return (object[])value;
    }
}

Die ConvertBack-Methode ist in diesem Fall nicht entscheidend bzw. wird nicht benötigt, weil das Binding nur in eine Richtung geht (OneWay).

 

Kommentar hinterlassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert