Gegevensbinding met niet-overeenkomende typen
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 bank
volgt 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:
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.
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 Color
waarde 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 eenStrength
opsommingswaarde. - De
targetType
parameter wordt genegeerd. Maar u kunt deze parameter gebruiken om te valideren dat het type eigenschap waarmee het conversieprogramma wordt gebruikt eenColor
. 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.Resources
volgende:
<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}}" ... />