Partager via


Xamarin.Forms Multi-Bindings

Les liaisons multiples 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 d’objets au sein de Binding 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 propriété Bindings est la propriété de contenu de la classe MultiBinding et n’a donc pas besoin d’être explicitement définie à partir du code 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 wen la valeur de la source est null.

Un MultiBinding doit utiliser une IMultiValueConverter valeur pour produire une valeur pour la cible de liaison, en fonction de la valeur des liaisons de la Bindings collection. 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.

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 Mode propriété d’un MultiBinding objet est définie TwoWaysur , toutes les liaisons de la collection sont prises en compte TwoWay , sauf si vous définissez explicitement une valeur différente Mode sur 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’interfaceIMultiValueConverter, puis implémentez les méthodes et ConvertBack les Convert méthodes :

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. Xamarin.Forms appelle cette méthode lorsqu’elle propage les valeurs des 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 produits.
  • 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 convertisseur.

La Convert méthode retourne une object valeur convertie 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 à Xamarin.Forms de ne pas effectuer d’action. Par exemple, pour indiquer à Xamarin.Forms 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 méthode qui reçoit nullConvert doit définir son TargetNullValue propety.

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 suggérées pour les valeurs retournées par la méthode.
  • 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 de la valeur cible vers les valeurs sources. Cette méthode doit retourner :

  • BindableProperty.UnsetValuei position pour indiquer que le convertisseur n’est pas en mesure de fournir une valeur pour la liaison source à l’indexi, et qu’aucune valeur n’est à définir sur celle-ci.
  • Binding.DoNothingi 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.

Consommer un IMultiValueConverter

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

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:DataBindingDemos"
             x:Class="DataBindingDemos.MultiBindingConverterPage"
             Title="MultiBinding Converter demo">

    <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 CheckBox.IsChecked propriété truesur , à condition que les trois Binding objets 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 ConvertBack méthode de l’instance AllTrueMultiConverter est exécutée lorsqu’elle CheckBox n’est pas case activée ed par l’utilisateur, ce qui définit les valeurs de liaison source sur la valeur de la CheckBox.IsChecked propriété.

Le code C# équivalent est illustré ci-dessous :

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

        CheckBox checkBox = new CheckBox();
        checkBox.SetBinding(CheckBox.IsCheckedProperty, new MultiBinding
        {
            Bindings = new Collection<BindingBase>
            {
                new Binding("Employee1.IsOver16"),
                new Binding("Employee1.HasPassedTest"),
                new Binding("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>

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é ci-dessous :

Label label = new Label();
label.SetBinding(Label.TextProperty, new MultiBinding
{
    Bindings = new Collection<BindingBase>
    {
        new Binding("Employee1.Forename"),
        new Binding("Employee1.MiddleName"),
        new Binding("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 et StringFormat des Converter propriétés, le convertisseur est appliqué à la valeur de données en premier, puis il StringFormat est appliqué.

Pour plus d’informations sur la mise en forme de chaîne dans Xamarin.Forms, consultez la mise en forme de chaîne Xamarin.Forms.

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. Pour ce faire, vous pouvez définir éventuellement les propriétés et TargetNullValue les FallbackValue propriétés d’un MultiBinding objet.

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 secours de liaison, consultez Xamarin.Forms Binding Fallbacks.

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://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:DataBindingDemos"
             x:Class="DataBindingDemos.NestedMultiBindingPage"
             Title="Nested MultiBinding demo">

    <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 AnyTrueMultiConverter instance pour définir la CheckBox.IsChecked propriété truesur , à condition que tous les Binding objets de l’objet interne MultiBinding évaluent trueou que l’objet Binding de l’objet de l’objet externe MultiBinding l’é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 permet de définir la source de liaison par rapport à la position de la cible de liaison :

<ContentPage ...
             xmlns:local="clr-namespace:DataBindingDemos"
             xmlns:xct="clr-namespace:Xamarin.CommunityToolkit.UI.Views;assembly=Xamarin.CommunityToolkit">
    <ContentPage.Resources>
        <local:AllTrueMultiConverter x:Key="AllTrueConverter" />

        <ControlTemplate x:Key="CardViewExpanderControlTemplate">
            <xct:Expander BindingContext="{Binding Source={RelativeSource TemplatedParent}}"
                          IsExpanded="{Binding IsExpanded, Source={RelativeSource TemplatedParent}}"
                          BackgroundColor="{Binding CardColor}">
                <xct:Expander.IsVisible>
                    <MultiBinding Converter="{StaticResource AllTrueConverter}">
                        <Binding Path="IsExpanded" />
                        <Binding Path="IsEnabled" />
                    </MultiBinding>
                </xct:Expander.IsVisible>
                <xct:Expander.Header>
                    <Grid>
                        <!-- XAML that defines Expander header goes here -->
                    </Grid>
                </xct:Expander.Header>
                <Grid>
                    <!-- XAML that defines Expander content goes here -->
                </Grid>
            </xct: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>

Remarque

Le Expander contrôle fait désormais partie de la communauté Xamarin Shared Computer Toolkit.

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é. L’élément Expanderracine du ControlTemplate, qui a sa BindingContext valeur définie sur l’instance d’objet runtime à laquelle le modèle est appliqué. Par conséquent, les Expander enfants et les enfants résolvent leurs expressions de liaison et Binding leurs objets, par rapport aux propriétés de l’objet CardViewExpander . L’instance utilise l’instance AllTrueMultiConverter pour définir la Expander.IsVisible propriété à true condition que les deux Binding objets soient évalués true.MultiBinding Sinon, la Expander.IsVisible propriété est définie sur false.

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