Liaison de données avec des types incompatibles
Parfois, les données que vous utilisez ne correspondent pas au type de données de la propriété de contrôle affichant les données. Par exemple, vous pouvez avoir une valeur monétaire stockée dans un type decimal
que vous souhaitez afficher sur un contrôle Label
, mis en forme en tant que devise. Un exemple plus compliqué serait avec l’application météorologique présentée dans le module. Une image est censée être affichée en fonction de la valeur d’énumération Sunny
ou Cloudy
de la prévision météorologique, mais vous ne pouvez pas lier la valeur d’énumération de la source à la propriété d’image d’une cible. Cette unité examine les façons dont vous pouvez convertir des données.
Mise en forme de chaîne
Un type intrinsèque que vous voulez afficher en tant que chaîne mise en forme constitue une incompatibilité de type courante. Comme lorsque vous souhaitez afficher des parties d’une valeur DateTime
ou mettre en forme un type decimal
en tant que devise.
Supposons que vous souhaitez afficher le montant dû sur une facture et que vous disposez de cette propriété sur votre objet de données :
public decimal BillAmount { get; set; }
Le montant dû est de 22,0304. Vous pouvez utiliser deux contrôles d’étiquette pour afficher du texte et le montant en dollar, comme illustré dans l’extrait de code suivant :
<HorizontalStackLayout>
<Label Text="You owe" Margin="0,0,5,0" />
<Label Text="{Binding BillAmount}" />
<Label Text="to the bank" Margin="5,0,0,0" />
</HorizontalStackLayout>
Cela génère une chaîne à l’interface utilisateur qui ressemble à You owe 22.0304 to the bank
, mais il manque le symbole monétaire et il peut y avoir trop de décimales, ou trop peu, en fonction de la devise locale. Normalement, vous traitez la valeur en tant que chaîne avec le spécificateur de format « C » (ou devise) dans le code, comme suit :
string formattedBillAmount = string.Format("{0:C}", BillAmount);
Toutefois, pour utiliser la mise en forme dans la liaison de données, l’objet de données doit vous fournir cette chaîne mise en forme en tant que propriété différente, ou vous devez l’intercepter d’une manière ou d’une autre et la mettre en forme vous-même. Heureusement, les liaisons .NET MAUI permettent de mettre en forme des chaînes avec la propriété de liaison StringFormat
. La chaîne de format suit les mêmes règles que la méthode String.Format
. Placez la chaîne de format entre guillemets simples afin que l’analyseur XAML ne soit pas dérouté par les accolades. Le paramètre 0
de format de chaîne est la valeur de propriété traitée par la liaison.
<Label Text="{Binding BillAmount, StringFormat='You owe {0:C} to the bank'}" />
Considérez le XAML suivant, qui illustre l’affichage de BillAmount
des deux façons :
<VerticalStackLayout Padding="10">
<HorizontalStackLayout>
<Label Text="You owe" Margin="0,0,5,0" />
<Label Text="{Binding BillAmount}" />
<Label Text="to the bank" Margin="5,0,0,0" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="{Binding BillAmount, StringFormat='You owe {0:C} to the bank'}" />
</HorizontalStackLayout>
</VerticalStackLayout>
L’image suivante illustre ce que produit la sortie XAML à l’écran :
Le XAML utilisant la propriété de liaison StringFormat
est plus simple que l’autre XAML et vous avez accès au système de mise en forme de chaîne puissant de .NET.
Personnaliser la conversion de type
La propriété de liaison StringFormat
est pratique lors de l’affichage d’une valeur sous forme de chaîne, mais pas lorsque vous souhaitez convertir quelque chose comme une Color
ou une Image
à partir d’un autre type. Dans ces cas, vous devez écrire du code de conversion personnalisé.
Supposons que vous invitez l’utilisateur à choisir un mot de passe et que vous souhaitez utiliser une couleur dans l’interface utilisateur pour indiquer la force du mot de passe. Il existe trois niveaux de force : faible, bon, fort. La force est basée sur le nombre de caractères dans le mot de passe. Pour donner des commentaires immédiats à l’utilisateur sur sa force de mot de passe, vous souhaitez que l’arrière-plan du contrôle Entry
contenant le mot de passe change en fonction de la force. L’image suivante illustre ces trois niveaux de force : faible, bon et fort.
Parmi les trois contrôles d’entrée de la capture d’écran, le premier comporte quatre caractères entrés et comporte un arrière-plan rouge. La deuxième comporte neuf caractères entrés et comporte un arrière-plan jaune. Le dernier contrôle d’entrée comporte 15 caractères et comporte un arrière-plan bleu.
Ces niveaux sont affectés à l’énumération Strength
:
private enum Strength
{
Weak,
Good,
Strong
}
Un objet de données est affecté en tant que BindingContext
de la page, qui contient la force du mot de passe avec la propriété PasswordStrength
. À mesure que l’utilisateur tape un mot de passe, la propriété PasswordStrength
est modifiée en fonction de la longueur du mot de passe. Étant donné que l’objet de données contient la propriété PasswordStrength
, vous liez cette propriété à la BackgroundColor
du contrôle Entry
:
<Entry BackgroundColor="{Binding PasswordStrength} ... />
Il y a toutefois un problème ici. La PasswordStrength
est de type Strength
alors que BackgroundColor
est une Color
. Ces types ne sont pas compatibles entre eux. .NET MAUI permet de résoudre ces problèmes d’incompatibilité de type, la propriété Converter
de la liaison.
Un convertisseur de liaison fait précisément ce que son nom indique. Il convertit entre la source et la cible de liaison. Les convertisseurs sont implémentés via l’interface IValueConverter
.
Implémenter IValueConverter
Vous créez votre logique de conversion dans une classe qui implémente l’interface IValueConverter
. En règle générale, les noms de ces classes se terminent par le nom Converter
pour rendre leur objectif clair.
L'interface IValueConverter
définit deux méthodes :
Convert
: convertit la propriété de la source de liaison en propriété de l’interface utilisateur de la cible de liaison.ConvertBack
: convertit la propriété de l’interface utilisateur de la cible de liaison en propriété de la source de liaison.Cette méthode est rarement utilisée et n’est pas utilisée dans ce scénario. La plupart des convertisseurs lèvent une exception
NotSupportedException
pour indiquer que cette conversion n’est pas prise en charge.
Voici le contrat de l’interface :
public interface IValueConverter
{
object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture);
object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture);
}
Rappelez-vous que le scénario avec lequel nous travaillons consiste à lier la propriété Entry.BackgroundColor
à la propriété PasswordStrength
de l’objet de données, qui est une énumération Strength
.
<Entry BackgroundColor="{Binding PasswordStrength} ... />
L’énumération Strength
doit être convertie en Color
. Par conséquent, le convertisseur doit évaluer la valeur Strength
fournie et retourner une Color
différente. Le code suivant illustre cette conversion :
namespace MyProject.Converters;
class StrengthToColorConverter : IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
return (Strength)value! switch
{
Strength.Weak => Colors.OrangeRed,
Strength.Good => Colors.Yellow,
Strength.Strong => Colors.LightBlue,
_ => Colors.LightBlue
};
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) =>
throw new NotImplementedException();
}
Décomposons ce code :
- La méthode
Convert
a quatre paramètres. Vous pouvez généralement ignorer les deux derniers paramètres, sauf si vous avez une raison spécifique de les utiliser. - Le paramètre
value
contient la valeur entrante. Dans cet exemple, il s’agit d’une valeur d’énumérationStrength
. - Le paramètre
targetType
est ignoré. Mais vous pouvez utiliser ce paramètre pour vérifier que le type de propriété avec lequel le convertisseur est utilisé est uneColor
. Cela est omis dans cet exemple par souci de simplicité. - Une expression de commutateur est utilisée pour retourner une couleur différente en fonction de la valeur de la
Strength
.
Utilisation du convertisseur en XAML
Une fois la classe de convertisseur créée, vous devez créer une instance de celle-ci et la référencer dans la liaison. La méthode standard pour instancier le convertisseur se trouve dans le dictionnaire de ressources de l’élément racine.
Tout d’abord, mappez un espace de noms XML à l’espace de noms .NET qui contient le convertisseur. Dans l’exemple de code suivant, l’espace de noms XML cvt
est mappé à l’espace de noms .NET MyProject.Converters
:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:cvt="clr-namespace:MyProject.Converters"
...
Ensuite, créez une instance dans ContentPage.Resources
:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:cvt="clr-namespace:MyProject.Converters"
x:Class="MyProject.PasswordExample">
<ContentPage.Resources>
<cvt:StrengthToColorConverter x:Key="StrengthToColorConverter" />
</ContentPage.Resources>
À présent, une instance du convertisseur se trouve dans le dictionnaire de ressources avec la clé StrengthToColorConverter
, qui se trouve avoir le même nom que le type. Il s’agit d’un moyen classique de nommer des convertisseurs, car vous n’avez généralement qu’un seul convertisseur que vous réutilisez tout au long du XAML. Si, pour une raison quelconque, vous avez besoin de plusieurs instances de convertisseur, les clés doivent être différentes entre elles.
Enfin, référencez le convertisseur sur la liaison. Étant donné que le convertisseur se trouve dans un dictionnaire de ressources, vous utilisez l’extension de balisage {StaticResource}
pour le référencer. Le convertisseur est affecté à la propriété de liaison Converter
:
<Entry BackgroundColor="{Binding PasswordStrength, Converter={StaticResource StrengthToColorConverter}}" ... />