Gegevensbinding met niet-overeenkomende typen

Voltooid

Soms komen de gegevens die u gebruikt niet overeen met het gegevenstype van de besturingselementeigenschap die de gegevens weergeeft. U hebt bijvoorbeeld een monetaire waarde opgeslagen in een decimal type dat u wilt weergeven in een Label besturingselement, opgemaakt als een valuta. Een ingewikkelder voorbeeld zou zijn met de weer-app die in de module wordt gepresenteerd. Een afbeelding moet worden weergegeven op basis van de weersvoorspelling Sunny of Cloudy opsommingswaarde, maar u kunt de opsommingswaarde van de bron niet binden aan de afbeeldingseigenschap van een doel. In deze les wordt gekeken naar manieren waarop u gegevens kunt converteren.

Tekenreeksopmaak

Een veelvoorkomend type komt niet overeen met een intrinsiek type dat u wilt weergeven als een opgemaakte tekenreeks. Bijvoorbeeld wanneer u delen van een DateTime waarde wilt weergeven of als u een decimal type wilt opmaken als valuta.

Stel dat u het verschuldigde bedrag wilt weergeven op een factuur en dat u deze eigenschap hebt voor uw gegevensobject:

public decimal BillAmount { get; set; }

Het verschuldigde bedrag is 22.0304. U kunt twee labelbesturingselementen gebruiken om tekst en het bedrag van de dollar weer te geven, zoals wordt weergegeven in het volgende fragment:

<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>

Hiermee wordt een tekenreeks uitgevoerd naar de gebruikersinterface die er als You owe 22.0304 to the bankvolgt uitziet, maar het valutasymbool ontbreekt en er mogelijk te veel of te weinig decimalen zijn op basis van de lokale valuta. Normaal gesproken verwerkt u de waarde als een tekenreeks met de notatie 'C' (of valuta) in code, zoals:

string formattedBillAmount = string.Format("{0:C}", BillAmount);

Maar als u opmaak in gegevensbinding wilt gebruiken, moet u het gegevensobject u die opgemaakte tekenreeks als een andere eigenschap geven of op een of andere manier onderscheppen en op de een of andere manier opmaken en opmaken. Gelukkig bieden .NET MAUI-bindingen een manier om tekenreeksen op te maken met de StringFormat bindingseigenschap. De notatietekenreeks volgt dezelfde regels als de String.Format methode. Plaats de notatietekenreeks tussen enkele aanhalingstekens, zodat de XAML-parser niet wordt verward door de accolades. De parameter 0 tekenreeksindeling is de eigenschapswaarde die door de binding wordt verwerkt.

<Label Text="{Binding BillAmount, StringFormat='You owe {0:C} to the bank'}" />

Houd rekening met de volgende XAML, die laat zien hoe u beide BillAmount manieren gebruikt:

<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>

In de volgende afbeelding ziet u wat de XAML-uitvoer op het scherm produceert:

Schermopname van een .NET MAUI Android-app met twee verschillende labelbesturingselementen met tekst die te wijten is aan een factuur. De tekst van één label is opgemaakt met usdvaluta.

De XAML met behulp van de StringFormat bindingseigenschap is eenvoudiger dan de andere XAML en u hebt toegang tot de . Het krachtige systeem voor tekenreeksopmaak van NET.

Conversie van aangepast type

De StringFormat bindingseigenschap is handig bij het weergeven van een waarde als een tekenreeks, maar niet wanneer u iets als een Color of Image ander type wilt converteren. In deze gevallen moet u aangepaste conversiecode schrijven.

Stel dat u de gebruiker vraagt een wachtwoord te kiezen en u een kleur in de gebruikersinterface wilt gebruiken om de sterkte van het wachtwoord aan te geven. Er zijn drie sterkteniveaus: zwak, goed, sterk. De kracht is gebaseerd op het aantal tekens in het wachtwoord. Als u onmiddellijk feedback wilt geven aan de gebruiker over hun wachtwoordsterkte, wilt u de achtergrond van het Entry besturingselement met het wachtwoord wijzigen op basis van de sterkte. In de volgende afbeelding ziet u de drie sterkteniveaus: zwak, goed en sterk.

Schermopname van een .NET MAUI Android-app met drie besturingselementen voor invoer, elk met een andere gekleurde achtergrond.

Van de drie invoerbesturingselementen in de schermafbeelding heeft de eerste vier tekens ingevoerd en heeft een rode achtergrond. De tweede heeft negen tekens ingevoerd en heeft een gele achtergrond. Het laatste invoerbesturingselement heeft 15 tekens en heeft een blauwe achtergrond.

Deze niveaus worden toegewezen aan de Strength opsomming:

private enum Strength
{
    Weak,
    Good,
    Strong
}

Een gegevensobject wordt toegewezen als de pagina's BindingContext, die de sterkte van het wachtwoord met de PasswordStrength eigenschap bevat. Wanneer de gebruiker een wachtwoord typt, wordt de PasswordStrength eigenschap gewijzigd op basis van de lengte van het wachtwoord. Omdat het gegevensobject de PasswordStrength eigenschap bevat, verbindt u die eigenschap met het BackgroundColor Entry besturingselement:

<Entry BackgroundColor="{Binding PasswordStrength} ... />

Er is hier echter een probleem. Het PasswordStrength is van het type Strength terwijl BackgroundColor het een Color. Deze typen zijn niet compatibel met elkaar. .NET MAUI biedt een manier om deze type-niet-overeenkomende problemen op te lossen, de eigenschap van Converter de binding.

Een bindingsconversieprogramma doet precies wat de naam ervan zegt, converteert tussen de bindingsbron en het doel. Conversieprogramma's worden geïmplementeerd via de IValueConverter interface.

IValue Converter implementeren

U maakt uw conversielogica in een klasse waarmee de IValueConverter interface wordt geïmplementeerd. Normaal gesproken eindigen de namen van deze klassen met de naam Converter om het doel ervan duidelijk te maken.

De IValueConverter interface definieert twee methoden:

  • Convert— Converteert van de eigenschap van de bindingsbron naar de gebruikersinterface-eigenschap van het bindingsdoel.

  • ConvertBack— Converteert van de gebruikersinterface-eigenschap van het bindingsdoel terug naar de eigenschap van de bindingsbron.

    Deze methode wordt zelden gebruikt en wordt niet gebruikt in dit scenario. De meeste conversieprogramma's geven aan NotSupportedException dat deze conversie niet wordt ondersteund.

Dit is het contract van de interface:

public interface IValueConverter
{
    object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture);
    object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture);
}

Zoals u weet, wordt de eigenschap gekoppeld aan de Entry.BackgroundColor eigenschap van PasswordStrength het gegevensobject. Dit is een Strength opsomming.

<Entry BackgroundColor="{Binding PasswordStrength} ... />

De Strength opsomming moet worden geconverteerd naar een Color. Het conversieprogramma moet dus evalueren welke Strength waarde wordt opgegeven en een andere Colorwaarde retourneren. De volgende code demonstreert deze conversie:

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();
}

Laten we deze code uitsplitsen:

  • De Convert methode heeft vier parameters. Over het algemeen kunt u de laatste twee parameters negeren, tenzij u een specifieke reden hebt om ze te gebruiken.
  • De value parameter bevat de binnenkomende waarde. In dit voorbeeld is het een Strength opsommingswaarde.
  • De targetType parameter wordt genegeerd. Maar u kunt deze parameter gebruiken om te valideren dat het type eigenschap waarmee het conversieprogramma wordt gebruikt een Color. Dit wordt weggelaten in dit voorbeeld voor eenvoud.
  • Een schakelexpressie wordt gebruikt om een andere kleur te retourneren op basis van de Strength waarde.

Het conversieprogramma gebruiken in XAML

Wanneer de conversieklasse is gemaakt, moet u er een exemplaar van maken en ernaar verwijzen in de binding. De standaardmethode om het conversieprogramma te instantiëren, bevindt zich in de resourcewoordenlijst van het hoofdelement.

Wijs eerst een XML-naamruimte toe aan de .NET-naamruimte die het conversieprogramma bevat. In het volgende codevoorbeeld wordt de cvt XML-naamruimte toegewezen aan de MyProject.Converters .NET-naamruimte:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:cvt="clr-namespace:MyProject.Converters"
             ...

Maak vervolgens een exemplaar in het ContentPage.Resourcesvolgende:

<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>

Nu bevindt een exemplaar van het conversieprogramma zich in de resourcewoordenlijst met de sleutel StrengthToColorConverter. Dit komt overeen met de naam van het type. Dit is een typische manier om conversieprogramma's te benoemen, omdat u over het algemeen slechts één conversieprogramma hebt dat u opnieuw gebruikt in de XAML. Als u om een of andere reden meerdere conversieprogramma-exemplaren vereist, moeten de sleutels ertussen verschillen.

Verwijs ten slotte naar het conversieprogramma op de binding. Omdat het conversieprogramma zich in een resourcewoordenlijst bevindt, gebruikt u de {StaticResource} markeringsextensie om ernaar te verwijzen. Het conversieprogramma wordt toegewezen aan de Converter bindingseigenschap:

<Entry BackgroundColor="{Binding PasswordStrength, Converter={StaticResource StrengthToColorConverter}}" ... />

Kennis testen

1.

Wat is de beste methode om een waarde weer te geven en op te maken als een tekenreeks in gegevensbinding?

2.

Welk type wordt gebruikt in de conversie van gegevensbindingen?