Freigeben über


Bindungswertkonverter

Browse sample. Durchsuchen Sie den Beispielcode

.NET Multi-platform App UI (.NET MAUI)-Datenbindungen übertragen normalerweise Daten von einer Quelleigenschaft zu einer Zieleigenschaft und in einigen Fällen von der Zieleigenschaft zur Quelleigenschaft. Diese Umwandlung ist einfach, wenn die Quell- und Zieleigenschaften vom gleichen Typ sind oder wenn ein Typ über eine implizite Konvertierung in den anderen Typ konvertiert werden kann. Wenn dies nicht der Fall ist, muss eine Typkonvertierung durchgeführt werden.

Im Artikel Zeichenfolgenformatierung haben Sie gesehen, wie Sie die StringFormat Eigenschaft einer Datenbindung verwenden können, um einen beliebigen Typ in eine Zeichenfolge zu konvertieren. Für andere Konvertierungstypen müssen Sie speziellen Code in einer Klasse schreiben, die die Schnittstelle IValueConverter implementiert. Klassen, die IValueConverter implementieren, werden Wertkonverter genannt. Sie werden allerdings auch oft als Bindungskonverter oder Bindungswertkonverter bezeichnet.

Bindungswertkonverter

Angenommen, Sie möchten eine Datenbindung definieren, bei der die Quelleigenschaft vom Typ int, die Zieleigenschaft jedoch vom Typ bool ist. Sie möchten, dass diese Datenbindung einen false-Wert erzeugt, wenn die Integerquelle gleich 0 ist und andernfalls true. Dies kann mit einer Klasse erreicht werden, welche die IValueConverter Schnittstelle implementiert:

public class IntToBoolConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (int)value != 0;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (bool)value ? 1 : 0;
    }
}

Sie setzen dann eine Instanz dieser Klasse auf die Converter Eigenschaft der Binding Klasse oder auf die Converter Eigenschaft der Binding Markup-Erweiterung. Diese Klasse wird Teil der Datenbindung.

Die Convert-Methode wird aufgerufen, wenn Daten von der Quelle zum Ziel in OneWay- oder TwoWay-Bindungen verschoben werden. Der Parameter value ist das Objekt oder der Wert der Quelle der Datenbindung. Die Methode muss einen Wert des Datenbindungszieltyps zurückgeben. Die hier dargestellte Methode wandelt den value-Parameter in eine int-Eigenschaft um und vergleicht diese dann mit „0“ für einen bool-Rückgabewert.

Die ConvertBack-Methode wird aufgerufen, wenn Daten vom Ziel zur Quelle in TwoWay- oder OneWayToSource-Bindungen verschoben werden. ConvertBack führt die umgekehrte Konvertierung aus: Diese Methode geht davon aus, dass der value-Parameter ein boolescher Wert (bool) aus dem Ziel ist und konvertiert diesen in einen int-Rückgabewert für die Quelle.

Hinweis

Wenn eine Datenbindung auch eine StringFormat-Einstellung enthält, wird der Wertkonverter aufgerufen, bevor das Ergebnis als Zeichenkette formatiert wird.

Im folgenden Beispiel wird die Verwendung dieses Wertkonverters in einer Datenbindung veranschaulicht:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:DataBindingDemos"
             x:Class="DataBindingDemos.EnableButtonsPage"
             Title="Enable Buttons">
    <ContentPage.Resources>
        <local:IntToBoolConverter x:Key="intToBool" />
    </ContentPage.Resources>

    <StackLayout Padding="10, 0">
        <Entry x:Name="entry1"
               Text=""
               Placeholder="enter search term"
               VerticalOptions="Center" />
        <Button Text="Search"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                IsEnabled="{Binding Source={x:Reference entry1},
                                    Path=Text.Length,
                                    Converter={StaticResource intToBool}}" />
        <Entry x:Name="entry2"
               Text=""
               Placeholder="enter destination"
               VerticalOptions="Center" />
        <Button Text="Submit"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                IsEnabled="{Binding Source={x:Reference entry2},
                                    Path=Text.Length,
                                    Converter={StaticResource intToBool}}" />
    </StackLayout>
</ContentPage>

In diesem Beispiel wird IntToBoolConverter im Ressourcenwörterbuch der Seite instanziiert. Es wird dann mit einer StaticResource Markuperweiterung referenziert, um die Converter-Eigenschaft in zwei Datenbindungen festzulegen. Es ist sehr üblich, Datenkonverter für mehrere Datenbindungen auf der Seite gemeinsam zu nutzen. Wenn ein Wertkonverter in mehreren Seiten Ihrer Anwendung verwendet wird, können Sie ihn im Ressourcenwörterbuch auf Anwendungsebene instanziieren.

Dieses Beispiel veranschaulicht eine häufige Notwendigkeit, wenn ein Button eine Operation auf der Grundlage von Text durchführt, den der/die Benutzer*innen in eine Entry-Ansicht eingibt. Die Text Eigenschaft jeder Entry wird mit einem leeren Zeichenfolge initialisiert, da die Text Eigenschaft standardmäßig null ist und die Datenbindung in diesem Fall nicht funktioniert. Wenn nichts in die Entry-Ansicht eingegeben wurde, sollte die Schaltfläche (Button) deaktiviert werden. Jede Button-Klasse enthält eine Datenbindung für ihre IsEnabled-Eigenschaft. Die Quelle der Datenbindung ist die Length-Eigenschaft der Text-Eigenschaft der entsprechenden Entry-Ansicht. Wenn diese Length-Eigenschaft nicht 0 (null) ist, gibt der Wertkonverter true zurück, und die Schaltfläche (Button) wird aktiviert:

Enable buttons.

Hinweis

Wenn Sie wissen, dass ein Wertkonverter nur in OneWay-Bindungen verwendet wird, kann die ConvertBack-Methode einfach null zurückgeben.

Die oben gezeigte Convert-Methode setzt voraus, dass das value-Argument vom Typ int ist und der Rückgabewert vom Typ bool sein muss. Gleichzeitig geht die ConvertBack-Methode davon aus, dass das value-Argument vom Typ bool und der Rückgabewert int ist. Sollte dies nicht der Fall sein, wird eine Laufzeitausnahme ausgelöst.

Sie können Wertkonverter so schreiben, dass sie verallgemeinert werden und mehrere unterschiedliche Datentypen akzeptieren. Die Methoden Convert und ConvertBack können die Operatoren as oder is mit dem value-Parameter verwenden oder GetType für diesen Parameter aufrufen, um dessen Typ zu bestimmen und dann einen entsprechenden Vorgang auszuführen. Der erwartete Typ des Rückgabewerts jeder Methode wird vom targetType-Parameter bestimmt. Manchmal werden Wertkonverter mit Datenbindungen unterschiedlicher Zieltypen verwendet. In diesem Fall kann der Wertkonverter das targetType Argument verwenden, um eine Kovertierung für den richtigen Typ auszuführen.

Sollte sich die durchgeführte Konvertierung für unterschiedliche Kulturen unterscheiden, verwenden Sie zu diesem Zweck den culture-Parameter.

Bindungskonverter-Eigenschaften

Wertkonverterklassen können über Eigenschaften und generische Parameter verfügen. Der folgende Wertkonverter wandelt ein bool aus der Quelle in ein Objekt vom Typ T für das Ziel um:

public class BoolToObjectConverter<T> : IValueConverter
{
    public T TrueObject { get; set; }
    public T FalseObject { get; set; }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (bool)value ? TrueObject : FalseObject;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return ((T)value).Equals(TrueObject);
    }
}

Das folgende Beispiel zeigt, wie dieser Konverter verwendet werden kann, um den Wert einer Switch Ansicht anzuzeigen. Obwohl es üblich ist, Wertkonverter als Ressourcen in einem Ressourcenwörterbuch zu instanziieren, zeigt dieses Beispiel eine Alternative auf. Hier wird jeder Wertumwandler zwischen Binding.Converter Eigenschaftselement-Tags instanziiert. Die Anweisung x:TypeArguments gibt das generische Argument an, und TrueObject und FalseObject werden jeweils auf Objekte dieses Typs festgelegt:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:DataBindingDemos"
             x:Class="DataBindingDemos.SwitchIndicatorsPage"
             Title="Switch Indicators">
    <ContentPage.Resources>
        <Style TargetType="Label">
            <Setter Property="FontSize" Value="18" />
            <Setter Property="VerticalOptions" Value="Center" />
        </Style>

        <Style TargetType="Switch">
            <Setter Property="VerticalOptions" Value="Center" />
        </Style>
    </ContentPage.Resources>

    <StackLayout Padding="10, 0">
        <StackLayout Orientation="Horizontal"
                     VerticalOptions="Center">
            <Label Text="Subscribe?" />
            <Switch x:Name="switch1" />
            <Label>
                <Label.Text>
                    <Binding Source="{x:Reference switch1}"
                             Path="IsToggled">
                        <Binding.Converter>
                            <local:BoolToObjectConverter x:TypeArguments="x:String"
                                                         TrueObject="Of course!"
                                                         FalseObject="No way!" />
                        </Binding.Converter>
                    </Binding>
                </Label.Text>
            </Label>
        </StackLayout>

        <StackLayout Orientation="Horizontal"
                     VerticalOptions="Center">
            <Label Text="Allow popups?" />
            <Switch x:Name="switch2" />
            <Label>
                <Label.Text>
                    <Binding Source="{x:Reference switch2}"
                             Path="IsToggled">
                        <Binding.Converter>
                            <local:BoolToObjectConverter x:TypeArguments="x:String"
                                                         TrueObject="Yes"
                                                         FalseObject="No" />
                        </Binding.Converter>
                    </Binding>
                </Label.Text>
                <Label.TextColor>
                    <Binding Source="{x:Reference switch2}"
                             Path="IsToggled">
                        <Binding.Converter>
                            <local:BoolToObjectConverter x:TypeArguments="Color"
                                                         TrueObject="Green"
                                                         FalseObject="Red" />
                        </Binding.Converter>
                    </Binding>
                </Label.TextColor>
            </Label>
        </StackLayout>

        <StackLayout Orientation="Horizontal"
                     VerticalOptions="Center">
            <Label Text="Learn more?" />
            <Switch x:Name="switch3" />
            <Label FontSize="18"
                   VerticalOptions="Center">
                <Label.Style>
                    <Binding Source="{x:Reference switch3}"
                             Path="IsToggled">
                        <Binding.Converter>
                            <local:BoolToObjectConverter x:TypeArguments="Style">
                                <local:BoolToObjectConverter.TrueObject>
                                    <Style TargetType="Label">
                                        <Setter Property="Text" Value="Indubitably!" />
                                        <Setter Property="FontAttributes" Value="Italic, Bold" />
                                        <Setter Property="TextColor" Value="Green" />
                                    </Style>
                                </local:BoolToObjectConverter.TrueObject>

                                <local:BoolToObjectConverter.FalseObject>
                                    <Style TargetType="Label">
                                        <Setter Property="Text" Value="Maybe later" />
                                        <Setter Property="FontAttributes" Value="None" />
                                        <Setter Property="TextColor" Value="Red" />
                                    </Style>
                                </local:BoolToObjectConverter.FalseObject>
                            </local:BoolToObjectConverter>
                        </Binding.Converter>
                    </Binding>
                </Label.Style>
            </Label>
        </StackLayout>
    </StackLayout>
</ContentPage>

In diesem Beispiel wird im letzten der drei Switch und Label Paare das generische Argument auf ein Style gesetzt, und für die Werte TrueObject und FalseObject werden ganze Style Objekte bereitgestellt. Diese überschreiben das impliziten Format für die im Ressourcenverzeichnis festgelegte Label-Klasse. Deshalb werden die Eigenschaften in diesem Format explizit zur Label-Klasse zugewiesen. Das Umschalten von Switch bewirkt, dass die entsprechende Label-Klasse die Änderung widerspiegelt:

Switch indicators.

Hinweis

Es ist auch möglich, Auslöser zu verwenden, um Änderungen in der Benutzeroberfläche basierend auf anderen Ansichten zu implementieren. Weitere Informationen finden Sie unter Trigger.

Parameter von Bindungskonvertern

Die Klasse Binding definiert eine ConverterParameter-Eigenschaft, und die Markuperweiterung Binding definiert ebenfalls eine ConverterParameter-Eigenschaft. Wenn diese Eigenschaft festgelegt ist, dann wird der Wert an die Methoden Convert und ConvertBack als parameter-Argument übergeben. Auch wenn die Instanz des Wertkonverters von mehreren Datenbindungen gemeinsam genutzt wird, kann ConverterParameter abweichen, um unterschiedliche Konvertierungen durchzuführen.

Die Verwendung der Eigenschaft ConverterParameter kann mit einem Farbauswahlprogramm demonstriert werden. Das folgende Beispiel zeigt die RgbColorViewModel, die drei Eigenschaften des Typs float mit den Namen Red, Green und Blue hat, die sie verwendet, um einen Color Wert zu konstruieren:

public class RgbColorViewModel : INotifyPropertyChanged
{
    Color color;
    string name;

    public event PropertyChangedEventHandler PropertyChanged;

    public float Red
    {
        get { return color.Red; }
        set
        {
            if (color.Red != value)
            {
                Color = new Color(value, color.Green, color.Blue);
            }
        }
    }

    public float Green
    {
        get { return color.Green; }
        set
        {
            if (color.Green != value)
            {
                Color = new Color(color.Red, value, color.Blue);
            }
        }
    }

    public float Blue
    {
        get { return color.Blue; }
        set
        {
            if (color.Blue != value)
            {
                Color = new Color(color.Red, color.Green, value);
            }
        }
    }

    public Color Color
    {
        get { return color; }
        set
        {
            if (color != value)
            {
                color = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Red"));
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Green"));
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Blue"));
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Color"));

                Name = NamedColor.GetNearestColorName(color);
            }
        }
    }

    public string Name
    {
        get { return name; }
        private set
        {
            if (name != value)
            {
                name = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
            }
        }
    }
}

Die Werte der Eigenschaften Red, Green und Blue können zwischen 0 und 1 liegen. Möglicherweise bevorzugen Sie, dass die Komponenten als zweistellige Hexadezimalwerte angezeigt werden. Damit sie diese als Hexadezimalwerte in XAML anzeigen können, müssen sie mit 255 multipliziert und in einen Integer konvertiert werden. Anschließend müssen Sie mit der Spezifikation „X2“ in die StringFormat-Eigenschaft formatiert werden. Die Multiplikation mit 255 und die Umwandlung in eine ganze Zahl kann durch den Wertkonverter erfolgen. Sie können den Wertkonverter so allgemein wie möglich gestalten, indem Sie den Multiplikationsfaktor mit der Eigenschaft ConverterParameter angeben. Das heißt, dass dieser die Convert- und ConvertBack-Methode als parameter-Argument angibt:

public class FloatToIntConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (int)Math.Round((float)value * GetParameter(parameter));
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (int)value / GetParameter(parameter);
    }

    double GetParameter(object parameter)
    {
        if (parameter is float)
            return (float)parameter;
        else if (parameter is int)
            return (int)parameter;
        else if (parameter is string)
            return float.Parse((string)parameter);

        return 1;
    }
}

In diesem Beispiel wird die Methode Convert von float in int konvertiert und multipliziert dabei mit dem parameter Wert. Die Methode ConvertBack teilt das ganzzahlige Argument value durch parameter und gibt ein float Ergebnis zurück.

Der Typ des parameter Arguments ist wahrscheinlich unterschiedlich, je nachdem, ob die Datenbindung in XAML oder Code definiert ist. Wenn die ConverterParameter-Eigenschaft von Binding in Code festgelegt ist, dann ist es wahrscheinlich, dass sie auf einen numerischen Wert festgelegt wird:

binding.ConverterParameter = 255;

Die ConverterParameter-Eigenschaft ist vom Typ Object, also interpretiert der C#-Compiler das Literal 255 als Integer und legt die Eigenschaft auf diesen Wert fest.

In XAML wird ConverterParameter jedoch wahrscheinlich wie folgt gesetzt werden:

<Label Text="{Binding Red,
                      Converter={StaticResource doubleToInt},
                      ConverterParameter=255,
                      StringFormat='Red = {0:X2}'}" />

Während 255 wie eine Zahl aussieht, weil ConverterParameter vom Typ Object ist, behandelt der XAML-Parser 255 als Zeichenfolge. Aus diesem Grund enthält der Wertkonverter eine separate GetParameter Methode, die Fälle behandelt, in denen parameter vom Typ float, int oder string ist.

Das folgende XAML-Beispiel instanziiert FloatToIntConverter in seinem Ressourcenwörterbuch:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:DataBindingDemos"
             x:Class="DataBindingDemos.RgbColorSelectorPage"
             Title="RGB Color Selector">
    <ContentPage.BindingContext>
        <local:RgbColorViewModel Color="Gray" />
    </ContentPage.BindingContext>
    <ContentPage.Resources>
        <Style TargetType="Slider">
            <Setter Property="VerticalOptions" Value="Center" />
        </Style>

        <Style TargetType="Label">
            <Setter Property="HorizontalTextAlignment" Value="Center" />
        </Style>

        <local:FloatToIntConverter x:Key="floatToInt" />
    </ContentPage.Resources>

    <StackLayout Margin="20">
        <BoxView Color="{Binding Color}"
                 HeightRequest="100"
                 WidthRequest="100"
                 HorizontalOptions="Center" />
        <StackLayout Margin="10, 0">
            <Label Text="{Binding Name}" />
            <Slider Value="{Binding Red}" />
            <Label Text="{Binding Red,
                                  Converter={StaticResource floatToInt},
                                  ConverterParameter=255,
                                  StringFormat='Red = {0:X2}'}" />
            <Slider Value="{Binding Green}" />
            <Label Text="{Binding Green,
                                  Converter={StaticResource floatToInt},
                                  ConverterParameter=255,
                                  StringFormat='Green = {0:X2}'}" />
            <Slider Value="{Binding Blue}" />
            <Label>
                <Label.Text>
                    <Binding Path="Blue"
                             StringFormat="Blue = {0:X2}"
                             Converter="{StaticResource floatToInt}">
                        <Binding.ConverterParameter>
                            <x:Single>255</x:Single>
                        </Binding.ConverterParameter>
                    </Binding>
                </Label.Text>
            </Label>
        </StackLayout>
    </StackLayout>
</ContentPage>

Die Werte der Eigenschaften Red und Green werden mit einer Binding-Markuperweiterung angezeigt. Die Blue-Eigenschaft instanziiert jedoch die Binding Klasse, um zu zeigen, wie ein expliziter float-Wert auf die ConverterParameter-Eigenschaft gesetzt werden kann:

RGB color selector.