Liaisons multiples

Parcourir l'exemple. Parcourir l'exemple

Les liaisons multiples de l’interface utilisateur d’application multiplateforme .NET (.NET MAUI) permettent d’attacher une collection d’objets Binding à une propriété cible de liaison unique. Ils sont créés avec la MultiBinding classe, qui évalue tous ses Binding objets et retourne une valeur unique via une IMultiValueConverter instance fournie par votre application. De plus, MultiBinding réévalue tous ses Binding objets lorsqu’une des données liées change.

La classe MultiBinding définit les propriétés suivantes :

  • Bindings, de type IList<BindingBase>, qui représente la collection de Binding objets au sein de l’instance MultiBinding.
  • Converter, de type IMultiValueConverter, qui représente le convertisseur à utiliser pour convertir les valeurs sources vers ou à partir de la valeur cible.
  • ConverterParameter, de type object, qui représente un paramètre facultatif à passer au Converter.

La Bindings propriété est la propriété de contenu de la MultiBinding classe et n’a donc pas besoin d’être définie explicitement à partir de XAML.

En outre, la MultiBinding classe hérite des propriétés suivantes de la BindingBase classe :

  • FallbackValue, de type object, qui représente la valeur à utiliser lorsque la liaison multiple ne peut pas retourner une valeur.
  • Mode, de type BindingMode, qui indique la direction du flux de données de la liaison multiple.
  • StringFormat, de type string, qui spécifie comment mettre en forme le résultat multi-liaison s’il est affiché sous forme de chaîne.
  • TargetNullValue, de type object, qui représente la valeur utilisée dans la cible lorsque la valeur de la source est null.

Un MultiBinding doit utiliser un IMultiValueConverter pour produire une valeur pour la cible de liaison, en fonction de la valeur des liaisons dans la collection Bindings. Par exemple, un Color peut être calculé à partir de valeurs rouges, bleues et vertes, qui peuvent être des valeurs provenant des mêmes objets sources de liaison ou différents. Lorsqu'une valeur passe de la cible aux sources, la valeur de la propriété cible est traduite en un ensemble de valeurs qui sont renvoyées dans les liaisons de données.

Important

Les liaisons individuelles de la Bindings collection peuvent avoir leurs propres convertisseurs de valeur.

La valeur de la Mode propriété détermine la fonctionnalité du MultiBinding, et est utilisée comme mode de liaison pour toutes les liaisons de la collection, sauf si une liaison individuelle remplace la propriété. Par exemple, si la propriété Mode sur un objet MultiBinding est définie sur TwoWay, toutes les liaisons de la collection sont considérées TwoWay, sauf si vous définissez explicitement une valeur différente Mode à l’une des liaisons.

Définir un IMultiValueConverter

L’interface IMultiValueConverter permet l’application d’une logique personnalisée à un MultiBinding. Pour associer un convertisseur à un MultiBinding, créez une classe qui implémente l’interface IMultiValueConverter, puis implémentez les méthodes Convert et ConvertBack.

public class AllTrueMultiConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values == null || !targetType.IsAssignableFrom(typeof(bool)))
        {
            return false;
            // Alternatively, return BindableProperty.UnsetValue to use the binding FallbackValue
        }

        foreach (var value in values)
        {
            if (!(value is bool b))
            {
                return false;
                // Alternatively, return BindableProperty.UnsetValue to use the binding FallbackValue
            }
            else if (!b)
            {
                return false;
            }
        }
        return true;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        if (!(value is bool b) || targetTypes.Any(t => !t.IsAssignableFrom(typeof(bool))))
        {
            // Return null to indicate conversion back is not possible
            return null;
        }

        if (b)
        {
            return targetTypes.Select(t => (object)true).ToArray();
        }
        else
        {
            // Can't convert back from false because of ambiguity
            return null;
        }
    }
}

La Convert méthode convertit les valeurs sources en valeur pour la cible de liaison. .NET MAUI appelle cette méthode lorsqu’elle propage des valeurs à partir de liaisons sources vers la cible de liaison. Cette méthode accepte quatre arguments :

  • values, de type object[], est un tableau de valeurs que les liaisons sources dans les MultiBinding produisent.
  • targetType, de type Type, est le type de la propriété cible de liaison.
  • parameter, de type object, est le paramètre de convertisseur à utiliser.
  • culture, de type CultureInfo, est la culture à utiliser dans le cadre de la conversion.

La méthode Convert retourne une object qui représente une valeur convertie. Cette méthode doit retourner :

  • BindableProperty.UnsetValue pour indiquer que le convertisseur n’a pas produit de valeur et que la liaison utilisera le FallbackValue.
  • Binding.DoNothing pour indiquer à .NET MAUI de ne pas effectuer d’action. Par exemple, pour indiquer à .NET MAUI de ne pas transférer une valeur vers la cible de liaison, ou de ne pas utiliser le FallbackValue.
  • null pour indiquer que le convertisseur ne peut pas effectuer la conversion et que la liaison utilisera le TargetNullValue.

Important

Une MultiBinding méthode qui reçoit BindableProperty.UnsetValue d’une Convert méthode doit définir sa FallbackValue propriété. De même, une MultiBinding qui reçoit null d'une méthode Convert doit définir sa propriété TargetNullValue.

La ConvertBack méthode convertit une cible de liaison en valeurs de liaison source. Cette méthode accepte quatre arguments :

  • value, de type object, est la valeur produite par la cible de liaison.
  • targetTypes, de type Type[], est le tableau de types à convertir. La longueur du tableau indique le nombre et les types de valeurs que la méthode doit retourner.
  • parameter, de type object, est le paramètre de convertisseur à utiliser.
  • culture, de type CultureInfo, est la culture à utiliser dans le convertisseur.

La ConvertBack méthode retourne un tableau de valeurs de type object[] qui ont été converties des valeurs cibles vers les valeurs sources. Cette méthode doit retourner :

  • BindableProperty.UnsetValue à la position i pour indiquer que le convertisseur n’est pas en mesure de fournir une valeur pour la liaison source à l’index i, et qu’aucune valeur ne doit y être définie.
  • Binding.DoNothing i position pour indiquer qu’aucune valeur n’est à définir sur la liaison source à l’indexi.
  • null pour indiquer que le convertisseur ne peut pas effectuer la conversion ou qu’il ne prend pas en charge la conversion dans cette direction.

Utiliser un IMultiValueConverter

IMultiValueConverter est généralement consommé en l’instanciant dans un dictionnaire de ressources, puis en le référençant à l’aide de l’extension de balisage StaticResource pour définir la propriété MultiBinding.Converter :

<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.MultiBindingConverterPage"
             Title="MultiBinding Converter demo"
             x:DataType="local:GroupViewModel">

    <ContentPage.Resources>
        <local:AllTrueMultiConverter x:Key="AllTrueConverter" />
        <local:InverterConverter x:Key="InverterConverter" />
    </ContentPage.Resources>

    <CheckBox>
        <CheckBox.IsChecked>
            <MultiBinding Converter="{StaticResource AllTrueConverter}">
                <Binding Path="Employee.IsOver16" />
                <Binding Path="Employee.HasPassedTest" />
                <Binding Path="Employee.IsSuspended"
                         Converter="{StaticResource InverterConverter}" />
            </MultiBinding>
        </CheckBox.IsChecked>
    </CheckBox>
</ContentPage>    

Dans cet exemple, l’objet MultiBinding utilise l’instance AllTrueMultiConverter pour définir la propriété CheckBox.IsChecked à true, à condition que les trois objets Binding soient évalués à true. Sinon, la CheckBox.IsChecked propriété est définie sur false.

Par défaut, la CheckBox.IsChecked propriété utilise une TwoWay liaison. Par conséquent, la méthode ConvertBack de l'instance AllTrueMultiConverter est exécutée lorsque CheckBox est décoché par l'utilisateur, ce qui fixe les valeurs de liaison de la source à la valeur de la propriété CheckBox.IsChecked.

Le code C# équivalent est illustré ici :

public class MultiBindingConverterCodePage : ContentPage
{
    public MultiBindingConverterCodePage()
    {
        BindingContext = new GroupViewModel();

        CheckBox checkBox = new CheckBox();
        checkBox.SetBinding(CheckBox.IsCheckedProperty, new MultiBinding
        {
            Bindings = new Collection<BindingBase>
            {
                Binding.Create(static (GroupViewModel vm) => vm.Employee1.IsOver16),
                Binding.Create(static (GroupViewModel vm) => vm.Employee1.HasPassedTest),
                Binding.Create(static (GroupViewModel vm) => vm.Employee1.IsSuspended, converter: new InverterConverter())
            },
            Converter = new AllTrueMultiConverter()
        });        

        Title = "MultiBinding converter demo";
        Content = checkBox;
    }
}

Chaînes de format

Un MultiBinding peut mettre en forme n’importe quel résultat multi-liaison affiché sous forme de chaîne, avec la StringFormat propriété. Cette propriété peut être définie sur une chaîne de mise en forme .NET standard, avec des espaces réservés, qui spécifie comment mettre en forme le résultat multi-liaison :

<Label>
    <Label.Text>
        <MultiBinding StringFormat="{}{0} {1} {2}">
            <Binding Path="Employee1.Forename" />
            <Binding Path="Employee1.MiddleName" />
            <Binding Path="Employee1.Surname" />
        </MultiBinding>
    </Label.Text>
</Label>

Note

Si la chaîne de format commence par le caractère {, l’analyseur XAML la confond pour une extension de balisage. Pour éviter cette ambiguïté, préfixez la chaîne de format avec des paires d'accolades vides.

Dans cet exemple, la StringFormat propriété combine les trois valeurs liées en une seule chaîne affichée par le Label.

Le code C# équivalent est illustré ici :

Label label = new Label();
label.SetBinding(Label.TextProperty, new MultiBinding
{
    Bindings = new Collection<BindingBase>
    {
        Binding.Create(static (GroupViewModel vm) => vm.Employee1.Forename),
        Binding.Create(static (GroupViewModel vm) => vm.Employee1.MiddleName),
        Binding.Create(static (GroupViewModel vm) => vm.Employee1.Surname)
    },
    StringFormat = "{0} {1} {2}"
});

Important

Le nombre de paramètres dans un format de chaîne composite ne peut pas dépasser le nombre d’objets enfants Binding dans le MultiBinding.

Lors de la définition des propriétés Converter et StringFormat, le convertisseur est d'abord appliqué à la valeur de la donnée, puis StringFormat est appliqué.

Pour plus d’informations sur la mise en forme de chaîne dans .NET MAUI, consultez Mise en forme de chaîne.

Fournir des valeurs de secours

Les liaisons de données peuvent être rendues plus robustes en définissant des valeurs de secours à utiliser si le processus de liaison échoue. Définissez les valeurs de secours en configurant les propriétés FallbackValue et TargetNullValue d'un objet MultiBinding.

Une MultiBinding utilise son FallbackValue lorsque la Convert méthode d’une IMultiValueConverter instance retourne BindableProperty.UnsetValue, ce qui indique que le convertisseur n’a pas produit de valeur. Une MultiBinding utilise son TargetNullValue lorsque la Convert méthode d’une IMultiValueConverter instance retourne null, ce qui indique que le convertisseur ne peut pas effectuer la conversion.

Pour plus d’informations sur les solutions de secours pour la liaison, consultez les solutions de secours pour la liaison.

Imbriquer des objets MultiBinding

MultiBinding les objets peuvent être imbriqués afin que plusieurs MultiBinding objets soient évalués pour retourner une valeur via une IMultiValueConverter instance :

<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.NestedMultiBindingPage"
             Title="Nested MultiBinding demo"
             x:DataType="local:GroupViewModel">

    <ContentPage.Resources>
        <local:AllTrueMultiConverter x:Key="AllTrueConverter" />
        <local:AnyTrueMultiConverter x:Key="AnyTrueConverter" />
        <local:InverterConverter x:Key="InverterConverter" />
    </ContentPage.Resources>

    <CheckBox>
        <CheckBox.IsChecked>
            <MultiBinding Converter="{StaticResource AnyTrueConverter}">
                <MultiBinding Converter="{StaticResource AllTrueConverter}">
                    <Binding Path="Employee.IsOver16" />
                    <Binding Path="Employee.HasPassedTest" />
                    <Binding Path="Employee.IsSuspended" Converter="{StaticResource InverterConverter}" />                        
                </MultiBinding>
                <Binding Path="Employee.IsMonarch" />
            </MultiBinding>
        </CheckBox.IsChecked>
    </CheckBox>
</ContentPage>

Dans cet exemple, l’objet MultiBinding utilise son instance AnyTrueMultiConverter pour définir la propriété CheckBox.IsChecked à true, à condition que tous les objets Binding de l’objet interne MultiBinding évaluent à true, ou si l’objet Binding dans l’objet externe MultiBinding évalue à true. Sinon, la CheckBox.IsChecked propriété est définie sur false.

Utiliser une liaison RelativeSource dans un MultiBinding

MultiBinding les objets prennent en charge les liaisons relatives, ce qui vous permet de définir la source de liaison par rapport à la position de la cible de liaison :

<ContentPage ...
             xmlns:local="clr-namespace:DataBindingDemos"
             xmlns:controls="clr-namespace:DataBindingDemos.Controls">
    <ContentPage.Resources>
        <local:AllTrueMultiConverter x:Key="AllTrueConverter" />

        <ControlTemplate x:Key="CardViewExpanderControlTemplate"
                         x:DataType="controls:CardViewExpander">
            <local:Expander BindingContext="{Binding Source={RelativeSource TemplatedParent}}"
                            IsExpanded="{Binding IsExpanded, Source={RelativeSource TemplatedParent}}"
                            BackgroundColor="{Binding CardColor}"
                            RowDefinitions="Auto,Auto"
                            Padding="8">
                <local:Expander.IsVisible>
                    <MultiBinding Converter="{StaticResource AllTrueConverter}">
                        <Binding Path="IsExpanded" />
                        <Binding Path="IsEnabled" />
                    </MultiBinding>
                </local:Expander.IsVisible>
                <Grid>
                    <!-- XAML that defines Expander header goes here -->
                </Grid>
                <Grid>
                    <!-- XAML that defines Expander content goes here -->
                </Grid>
            </local:Expander>
        </ControlTemplate>
    </ContentPage.Resources>

    <StackLayout>
        <controls:CardViewExpander BorderColor="DarkGray"
                                   CardTitle="John Doe"
                                   CardDescription="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla elit dolor, convallis non interdum."
                                   IconBackgroundColor="SlateGray"
                                   IconImageSource="user.png"
                                   ControlTemplate="{StaticResource CardViewExpanderControlTemplate}"
                                   IsEnabled="True"
                                   IsExpanded="True" />
    </StackLayout>
</ContentPage>

Dans cet exemple, le TemplatedParent mode de liaison relative est utilisé pour lier à partir d’un modèle de contrôle à l’instance d’objet runtime à laquelle le modèle est appliqué. Expander, qui est l'élément racine du ControlTemplate, a sa valeur BindingContext définie sur l'instance d'objet en cours d'exécution à laquelle le modèle est appliqué. Par conséquent, Expander et ses enfants résolvent leurs expressions de liaison, ainsi que les objets Binding, par rapport aux propriétés de l’objet CardViewExpander. L’MultiBinding utilise l’instance AllTrueMultiConverter pour définir la propriété Expander.IsVisible sur true à condition que les deux objets Binding évaluent à true. Sinon, la Expander.IsVisible propriété est définie sur false.

Pour plus d’informations sur les liaisons relatives, consultez Liaisons relatives. Pour plus d’informations sur les modèles de contrôle, consultez Modèles de contrôle.