Liaison de données avec des types incompatibles

Effectué

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 :

Screenshot of a .NET MAUI Android app displaying two different label controls with text related to owing a bill. One label's text is formatted with USD currency.

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.

Screenshot of a .NET MAUI Android app with three entry controls, each with a different colored background.

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ération Strength.
  • 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 une Color. 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}}" ... />

Contrôle de vos connaissances

1.

Pour afficher et mettre en forme une valeur sous forme de chaîne dans la liaison de données, quelle est la meilleure approche ?

2.

Quel type est utilisé dans la conversion de liaison de données ?