Principes de base de la liaison de données

Browse sample. Parcourir l’exemple

Les liaisons de données de l’interface utilisateur d’application multiplateforme .NET (.NET MAUI) permettent aux propriétés de deux objets d’être liés afin qu’une modification d’une modification provoque une modification dans l’autre. Il s’agit d’un outil très précieux et, bien que les liaisons de données puissent être définies entièrement dans le code, XAML fournit des raccourcis et des commodités.

Liaisons de données

Les liaisons de données connectent les propriétés de deux objets, appelées source et cible. Dans le code, deux étapes sont requises :

  1. La BindingContext propriété de l’objet cible doit être définie sur l’objet source,
  2. La SetBinding méthode (souvent utilisée conjointement avec la Binding classe) doit être appelée sur l’objet cible pour lier une propriété de cet objet à une propriété de l’objet source.

La propriété cible doit être une propriété pouvant être liée, ce qui signifie que l’objet cible doit dériver de BindableObject. Une propriété de Label, telle que Text, est associée à la propriété TextPropertypouvant être liée .

En XAML, vous devez également effectuer les deux étapes requises dans le code, sauf que l’extension Binding de balisage prend la place de l’appel SetBinding et de la Binding classe. Toutefois, lorsque vous définissez des liaisons de données en XAML, il existe plusieurs façons de définir l’objet BindingContext cible. Parfois, il est défini à partir du fichier code-behind, parfois à l’aide d’une extension ou x:Static d’une StaticResource extension de balisage, et parfois comme contenu des balises d’élément BindingContext de propriété.

Liaisons d’affichage à vue

Vous pouvez définir des liaisons de données pour lier des propriétés de deux vues sur la même page. Dans ce cas, vous définissez l’objet BindingContext cible à l’aide de l’extension de x:Reference balisage.

L’exemple suivant contient une Slider et deux Label vues, dont l’une est pivotée par la Slider valeur et une autre qui affiche la Slider valeur :

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.SliderBindingsPage"
             Title="Slider Bindings Page">
    <StackLayout>
        <Label Text="ROTATION"
               BindingContext="{x:Reference slider}"
               Rotation="{Binding Path=Value}"
               FontAttributes="Bold"
               FontSize="18"
               HorizontalOptions="Center"
               VerticalOptions="Center" />
        <Slider x:Name="slider"
                Maximum="360"
                VerticalOptions="Center" />
        <Label BindingContext="{x:Reference slider}"
               Text="{Binding Value, StringFormat='The angle is {0:F0} degrees'}"
               FontAttributes="Bold"
               FontSize="18"
               HorizontalOptions="Center"
               VerticalOptions="Center" />
    </StackLayout>
</ContentPage>

Contient Slider un x:Name attribut référencé par les deux Label vues à l’aide de l’extension de x:Reference balisage. L’extension x:Reference de liaison définit une propriété nommée Name pour définir le nom de l’élément référencé, dans ce cas slider. Toutefois, la ReferenceExtension classe qui définit l’extension de x:Reference balisage définit également un ContentProperty attribut pour Name, ce qui signifie qu’elle n’est pas explicitement requise.

L’extension Binding de balisage elle-même peut avoir plusieurs propriétés, comme la classe et Binding la BindingBase classe. Pour ContentProperty celaPath, mais la partie « Path= » de l’extension de balisage peut être omise si le chemin est le premier élément de l’extension de Binding balisage.Binding

La deuxième Binding extension de balisage définit la StringFormat propriété. Dans .NET MAUI, les liaisons n’effectuent aucune conversion de type implicite et, si vous devez afficher un objet non-chaîne en tant que chaîne, vous devez fournir un convertisseur de type ou utiliser StringFormat.

Important

Les chaînes de mise en forme doivent être placées entre guillemets simples.

Mode de liaison

Une vue unique peut avoir des liaisons de données sur plusieurs de ses propriétés. Toutefois, chaque vue ne peut avoir qu’un seul BindingContext, donc plusieurs liaisons de données sur cette vue doivent toutes les propriétés de référence du même objet.

La solution à ceci et à d’autres problèmes implique la Mode propriété, qui est définie sur un membre de l’énumération BindingMode :

  • Default
  • OneWay — les valeurs sont transférées de la source vers la cible
  • OneWayToSource — les valeurs sont transférées de la cible à la source
  • TwoWay — les valeurs sont transférées de deux façons entre la source et la cible
  • OneTime — les données vont de la source à la cible, mais uniquement lorsque les BindingContext modifications

L’exemple suivant illustre une utilisation courante des modes de liaison et TwoWay de OneWayToSource liaison :

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.SliderTransformsPage"
             Padding="5"
             Title="Slider Transforms Page">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>

        <!-- Scaled and rotated Label -->
        <Label x:Name="label"
               Text="TEXT"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand" />

        <!-- Slider and identifying Label for Scale -->
        <Slider x:Name="scaleSlider"
                BindingContext="{x:Reference label}"
                Grid.Row="1" Grid.Column="0"
                Maximum="10"
                Value="{Binding Scale, Mode=TwoWay}" />
        <Label BindingContext="{x:Reference scaleSlider}"
               Text="{Binding Value, StringFormat='Scale = {0:F1}'}"
               Grid.Row="1" Grid.Column="1"
               VerticalTextAlignment="Center" />

        <!-- Slider and identifying Label for Rotation -->
        <Slider x:Name="rotationSlider"
                BindingContext="{x:Reference label}"
                Grid.Row="2" Grid.Column="0"
                Maximum="360"
                Value="{Binding Rotation, Mode=OneWayToSource}" />
        <Label BindingContext="{x:Reference rotationSlider}"
               Text="{Binding Value, StringFormat='Rotation = {0:F0}'}"
               Grid.Row="2" Grid.Column="1"
               VerticalTextAlignment="Center" />

        <!-- Slider and identifying Label for RotationX -->
        <Slider x:Name="rotationXSlider"
                BindingContext="{x:Reference label}"
                Grid.Row="3" Grid.Column="0"
                Maximum="360"
                Value="{Binding RotationX, Mode=OneWayToSource}" />
        <Label BindingContext="{x:Reference rotationXSlider}"
               Text="{Binding Value, StringFormat='RotationX = {0:F0}'}"
               Grid.Row="3" Grid.Column="1"
               VerticalTextAlignment="Center" />

        <!-- Slider and identifying Label for RotationY -->
        <Slider x:Name="rotationYSlider"
                BindingContext="{x:Reference label}"
                Grid.Row="4" Grid.Column="0"
                Maximum="360"
                Value="{Binding RotationY, Mode=OneWayToSource}" />
        <Label BindingContext="{x:Reference rotationYSlider}"
               Text="{Binding Value, StringFormat='RotationY = {0:F0}'}"
               Grid.Row="4" Grid.Column="1"
               VerticalTextAlignment="Center" />
    </Grid>
</ContentPage>

Dans cet exemple, quatre Slider vues sont destinées à contrôler les propriétés , et RotateYRotateRotateXles Scalepropriétés d’un .Label Au début, il semble que ces quatre propriétés de la Label liaison de données doivent être des cibles de liaison de données, car chacune est définie par un Slider. Toutefois, il BindingContext ne peut s’agir que d’un Label seul objet et il existe quatre curseurs différents. Pour cette raison, les BindingContext quatre curseurs sont définis sur le Labelcurseur et les liaisons sont définies sur les Value propriétés des curseurs. En utilisant les modes et les OneWayToSource modes, ces Value propriétés peuvent définir les propriétés sources, qui sont les Scalepropriétés , Rotateet RotateXRotateY les propriétés de l’objet .LabelTwoWay

Les liaisons sur trois des Slider vues sont OneWayToSource, ce qui signifie que la Slider valeur provoque une modification dans la propriété de son BindingContext, qui est le nom .labelLabel Ces trois Slider vues entraînent des modifications apportées aux propriétés et RotateXRotateY aux Rotatepropriétés des Labeléléments suivants :

Reverse bindings.

Toutefois, la liaison de la Scale propriété est TwoWay. Cela est dû au fait que la propriété a une valeur par défaut de 1 et que l’utilisation Scale d’une TwoWay liaison entraîne la définition de la Slider valeur initiale à 1 au lieu de 0. Si cette liaison était OneWayToSource, la Scale propriété est initialement définie sur 0 à partir de la Slider valeur par défaut. Il Label ne serait pas visible

Remarque

La VisualElement classe a ScaleX également et ScaleY les propriétés, qui mettez à l’échelle respectivement l’axe VisualElement x et l’axe y.

Liaisons et collections

ListView définit une ItemsSource propriété de type IEnumerableet affiche les éléments de cette collection. Ces éléments peuvent être des objets de n’importe quel type. Par défaut, ListView utilise la ToString méthode de chaque élément pour afficher cet élément. Parfois, c’est juste ce que vous voulez, mais dans de nombreux cas, ToString retourne uniquement le nom de classe complet de l’objet.

Toutefois, les éléments de la ListView collection peuvent être affichés comme vous le souhaitez par le biais de l’utilisation d’un modèle, ce qui implique une classe qui dérive de Cell. Le modèle est cloné pour chaque élément dans les ListViewliaisons de données qui ont été définies sur le modèle sont transférées vers les clones individuels. Les cellules personnalisées peuvent être créées pour les éléments à l’aide de la ViewCell classe.

ListView peut afficher une liste de chaque couleur nommée disponible dans .NET MAUI, avec l’aide de la NamedColor classe :

using System.Reflection;
using System.Text;

namespace XamlSamples
{
    public class NamedColor
    {
        public string Name { get; private set; }
        public string FriendlyName { get; private set; }
        public Color Color { get; private set; }

        // Expose the Color fields as properties
        public float Red => Color.Red;
        public float Green => Color.Green;
        public float Blue => Color.Blue;

        public static IEnumerable<NamedColor> All { get; private set; }

        static NamedColor()
        {
            List<NamedColor> all = new List<NamedColor>();
            StringBuilder stringBuilder = new StringBuilder();

            // Loop through the public static fields of the Color structure.
            foreach (FieldInfo fieldInfo in typeof(Colors).GetRuntimeFields())
            {
                if (fieldInfo.IsPublic &&
                    fieldInfo.IsStatic &&
                    fieldInfo.FieldType == typeof(Color))
                {
                    // Convert the name to a friendly name.
                    string name = fieldInfo.Name;
                    stringBuilder.Clear();
                    int index = 0;

                    foreach (char ch in name)
                    {
                        if (index != 0 && Char.IsUpper(ch))
                        {
                            stringBuilder.Append(' ');
                        }
                        stringBuilder.Append(ch);
                        index++;
                    }

                    // Instantiate a NamedColor object.
                    NamedColor namedColor = new NamedColor
                    {
                        Name = name,
                        FriendlyName = stringBuilder.ToString(),
                        Color = (Color)fieldInfo.GetValue(null)
                    };

                    // Add it to the collection.
                    all.Add(namedColor);
                }
            }
            all.TrimExcess();
            All = all;
        }
    }
}

Chaque NamedColor objet a Name et FriendlyName propriétés de type string, une Color propriété de type Color, et Red, Greenet Blue des propriétés. En outre, le NamedColor constructeur statique crée une IEnumerable<NamedColor> collection qui contient NamedColor des objets correspondant aux champs de type Color de la Colors classe et l’affecte à sa propriété statique All publique.

La définition de la propriété statique NamedColor.All sur l’une ItemsSource d’elles ListView peut être obtenue à l’aide de l’extension de x:Static balisage :

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:XamlSamples;assembly=XamlSamples"
             x:Class="XamlSamples.ListViewDemoPage"
             Title="ListView Demo Page">
    <ListView ItemsSource="{x:Static local:NamedColor.All}" />
</ContentPage>

Le résultat établit que les éléments sont de type XamlSamples.NamedColor:

Binding to a collection.

Pour définir un modèle pour les éléments, il ItemTemplate doit être défini sur un DataTemplate modèle qui fait référence à un ViewCell. Il ViewCell doit définir une disposition d’une ou plusieurs vues pour afficher chaque élément :

<ListView ItemsSource="{x:Static local:NamedColor.All}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <Label Text="{Binding FriendlyName}" />
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Remarque

La source de liaison pour les cellules et les enfants de cellules est la ListView.ItemsSource collection.

Dans cet exemple, l’élément Label est défini sur la View propriété du ViewCell. Les ViewCell.View balises ne sont pas nécessaires, car la View propriété est la propriété de contenu de ViewCell. Ce code XAML affiche la FriendlyName propriété de chaque NamedColor objet :

Binding to a collection with a DataTemplate.

Le modèle d’élément peut être développé pour afficher plus d’informations et la couleur réelle :

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:XamlSamples"
             x:Class="XamlSamples.ListViewDemoPage"
             Title="ListView Demo Page">
    <ContentPage.Resources>
        <x:Double x:Key="boxSize">50</x:Double>
        <x:Int32 x:Key="rowHeight">60</x:Int32>
        <local:FloatToIntConverter x:Key="intConverter" />
    </ContentPage.Resources>

    <ListView ItemsSource="{x:Static local:NamedColor.All}"
              RowHeight="{StaticResource rowHeight}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout Padding="5, 5, 0, 5"
                                 Orientation="Horizontal"
                                 Spacing="15">
                        <BoxView WidthRequest="{StaticResource boxSize}"
                                 HeightRequest="{StaticResource boxSize}"
                                 Color="{Binding Color}" />
                        <StackLayout Padding="5, 0, 0, 0"
                                     VerticalOptions="Center">
                            <Label Text="{Binding FriendlyName}"
                                   FontAttributes="Bold"
                                   FontSize="14" />
                            <StackLayout Orientation="Horizontal"
                                         Spacing="0">
                                <Label Text="{Binding Red,
                                                      Converter={StaticResource intConverter},
                                                      ConverterParameter=255,
                                                      StringFormat='R={0:X2}'}" />                                
                                <Label Text="{Binding Green,
                                                      Converter={StaticResource intConverter},
                                                      ConverterParameter=255,
                                                      StringFormat=', G={0:X2}'}" />                                
                                <Label Text="{Binding Blue,
                                                      Converter={StaticResource intConverter},
                                                      ConverterParameter=255,
                                                      StringFormat=', B={0:X2}'}" />
                            </StackLayout>
                        </StackLayout>
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage>

Convertisseurs de valeur de liaison

L’exemple XAML précédent affiche les propriétés individuelles Red, Greenet Blue les propriétés de chacun d’eux NamedColor. Ces propriétés sont de type float et vont de 0 à 1. Si vous souhaitez afficher les valeurs hexadécimales, vous ne pouvez pas simplement utiliser StringFormat avec une spécification de mise en forme « X2 ». Cela ne fonctionne que pour les entiers et en plus, les float valeurs doivent être multipliées par 255.

Ce problème peut être résolu avec un convertisseur de valeur, également appelé convertisseur de liaison. Il s’agit d’une classe qui implémente l’interface IValueConverter , ce qui signifie qu’elle a deux méthodes nommées Convert et ConvertBack. La Convert méthode est appelée lorsqu’une valeur est transférée de la source à la cible. La ConvertBack méthode est appelée pour les transferts de la cible vers la source dans OneWayToSource ou TwoWay les liaisons :

using System.Globalization;

namespace XamlSamples
{
    public class FloatToIntConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            float multiplier;

            if (!float.TryParse(parameter as string, out multiplier))
                multiplier = 1;

            return (int)Math.Round(multiplier * (float)value);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            float divider;

            if (!float.TryParse(parameter as string, out divider))
                divider = 1;

            return ((float)(int)value) / divider;
        }
    }
}

Remarque

La ConvertBack méthode ne joue pas de rôle dans cet exemple, car les liaisons ne sont qu’une seule façon de passer de la source à la cible.

Une liaison fait référence à un convertisseur de liaison avec la Converter propriété. Un convertisseur de liaison peut également accepter un paramètre spécifié avec la ConverterParameter propriété. Pour une certaine polyvalence, il s’agit de la façon dont le multiplicateur est spécifié. Le convertisseur de liaison case activée le paramètre de convertisseur pour une valeur validefloat.

Le convertisseur est instancié dans le dictionnaire de ressources de la page afin qu’il puisse être partagé entre plusieurs liaisons :

<local:FloatToIntConverter x:Key="intConverter" />

Trois liaisons de données font référence à cette instance unique :

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

Le modèle d’élément dsplaye la couleur, son nom convivial et ses valeurs RVB :

Binding to a collection with a DataTemplate and a converter.

Il ListView peut gérer les modifications qui se produisent dynamiquement dans les données sous-jacentes, mais uniquement si vous effectuez certaines étapes. Si la collection d’éléments affectés à la propriété des modifications pendant l’exécution ItemsSourceListView , utilisez une ObservableCollection<T> classe pour ces éléments. ObservableCollection<T> implémente l’interface INotifyCollectionChanged et ListView installe un gestionnaire pour l’événement CollectionChanged .

Si les propriétés des éléments eux-mêmes changent pendant l’exécution, les éléments de la collection doivent implémenter l’interface INotifyPropertyChanged et signaler les modifications apportées aux valeurs de propriété à l’aide de l’événement PropertyChanged .

Étapes suivantes

Les liaisons de données fournissent un mécanisme puissant pour lier des propriétés entre deux objets au sein d’une page ou entre des objets visuels et des données sous-jacentes. Mais lorsque l’application commence à travailler avec des sources de données, un modèle architectural d’application populaire commence à apparaître comme un paradigme utile.