Principes de base de la liaison de données
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 :
- La
BindingContext
propriété de l’objet cible doit être définie sur l’objet source, - La
SetBinding
méthode (souvent utilisée conjointement avec laBinding
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é TextProperty
pouvant ê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 cibleOneWayToSource
— les valeurs sont transférées de la cible à la sourceTwoWay
— les valeurs sont transférées de deux façons entre la source et la cibleOneTime
— les données vont de la source à la cible, mais uniquement lorsque lesBindingContext
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 RotateY
Rotate
RotateX
les Scale
proprié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 Scale
propriétés , Rotate
et RotateX
RotateY
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 .label
Label Ces trois Slider vues entraînent des modifications apportées aux propriétés et RotateX
RotateY
aux Rotate
propriétés des Labeléléments suivants :
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. Ce Label n’est 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 IEnumerable
et 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
, Green
et 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
:
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 :
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 valeurs de liaison
L’exemple XAML précédent affiche les propriétés individuelles Red
, Green
et 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 vérifie le paramètre de convertisseur pour une valeur valide float
.
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 :
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 ItemsSource
ListView , 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.