Databindning med felmatchade typer
Ibland matchar inte de data som du använder datatypen för kontrollegenskapen som visar data. Du kan till exempel ha ett penningvärde som lagras i en decimal
typ som du vill visa på en Label
kontroll, formaterad som en valuta. Ett mer komplicerat exempel skulle vara med väderappen som visas i modulen. En bild ska visas baserat på väderprognosens eller Cloudy
uppräkningsvärdetSunny
, men du kan inte binda källans uppräkningsvärde till ett måls bildegenskap. I den här lektionen går vi igenom hur du kan konvertera data.
Strängformatering
Ett vanligt typmatchningsfel är en inbyggd typ som du vill visa som en formaterad sträng. Som när du vill visa delar av ett DateTime
värde eller om du vill formatera en decimal
typ som valuta.
Anta att du vill visa det belopp som ska betalas på en faktura och att du har den här egenskapen för dataobjektet:
public decimal BillAmount { get; set; }
Det belopp som är skyldigt blir 22.0304. Du kan använda två etikettkontroller för att visa text och dollarbeloppet enligt följande kodfragment:
<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>
Detta matar ut en sträng till användargränssnittet som ser ut som You owe 22.0304 to the bank
, men den saknar valutasymbolen och det kan finnas för många eller för få decimaler baserat på den lokala valutan. Normalt bearbetar du värdet som en sträng med formatspecificeraren "C" (eller valuta) i koden, så här:
string formattedBillAmount = string.Format("{0:C}", BillAmount);
Men om du vill använda formatering i databindning måste du antingen låta dataobjektet ange den formaterade strängen som en annan egenskap, eller fånga upp den på något sätt och formatera den själv. Lyckligtvis är .NET MAUI-bindningar ett sätt att formatera strängar med bindningsegenskapen StringFormat
. Formatsträngen följer samma regler som String.Format
metoden. Omslut formatsträngen med enkla citattecken så att XAML-parsern inte blir förvirrad av klammerparenteserna. Strängformatparametern 0
är egenskapsvärdet som bearbetas av bindningen.
<Label Text="{Binding BillAmount, StringFormat='You owe {0:C} to the bank'}" />
Överväg följande XAML, som visar hur du visar hur du använder båda sätten BillAmount
:
<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>
Följande bild visar vad XAML-utdata producerar på skärmen:
XAML med bindningsegenskapen StringFormat
är enklare än den andra XAML och du har åtkomst till . NET:s kraftfulla strängformateringssystem.
Konvertering av anpassad typ
Bindningsegenskapen StringFormat
är praktisk när du visar ett värde som en sträng, men inte när du vill konvertera något som liknar en eller Image
från en Color
annan typ. I dessa fall måste du skriva anpassad konverteringskod.
Anta att du uppmanar användaren att välja ett lösenord och att du vill använda en färg i användargränssnittet för att ange lösenordets styrka. Det finns tre nivåer av styrka: svag, bra, stark. Styrkan baseras på hur många tecken som finns i lösenordet. Om du vill ge omedelbar feedback till användaren om deras lösenordsstyrka vill du att bakgrunden till kontrollen Entry
som innehåller lösenordet ska ändras baserat på styrkan. Följande bild visar dessa tre styrkenivåer: svaga, bra och starka.
Av de tre postkontrollerna i skärmbilden har den första fyra tecken angivna och har en röd bakgrund. Den andra har nio tecken angivna och har en gul bakgrund. Den senaste inmatningskontrollen har 15 tecken och har en blå bakgrund.
Dessa nivåer tilldelas till Strength
uppräkningen:
private enum Strength
{
Weak,
Good,
Strong
}
Ett dataobjekt tilldelas som sidans BindingContext
, som innehåller lösenordets styrka med PasswordStrength
egenskapen . När användaren skriver in ett lösenord PasswordStrength
ändras egenskapen enligt lösenordets längd. Eftersom dataobjektet innehåller PasswordStrength
egenskapen binder du den egenskapen till BackgroundColor
Entry
kontrollens:
<Entry BackgroundColor="{Binding PasswordStrength} ... />
Det finns dock ett problem här. PasswordStrength
Är av typen Strength
medan BackgroundColor
är en Color
. Dessa typer är inte kompatibla med varandra. .NET MAUI är ett sätt att åtgärda dessa typmatchningsproblem, bindningens Converter
egenskap.
En bindningskonverterare gör precis vad namnet säger, konverterar mellan bindningskällan och målet. Konverterare implementeras via IValueConverter
gränssnittet.
Implementera IValueConverter
Du skapar konverteringslogik i en klass som implementerar IValueConverter
gränssnittet. Vanligtvis slutar namnen på dessa klasser med namnet Converter
för att göra dess syfte tydligt.
Gränssnittet IValueConverter
definierar två metoder:
Convert
– Konverterar från bindningskällans egenskap till bindningsmålets UI-egenskap.ConvertBack
– Konverterar från bindningsmålets UI-egenskap tillbaka till bindningskällans egenskap.Den här metoden används sällan och används inte i det här scenariot. De flesta konverterare genererar en
NotSupportedException
för att indikera att den här konverteringen inte stöds.
Här är gränssnittets kontrakt:
public interface IValueConverter
{
object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture);
object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture);
}
Kom ihåg att scenariot vi arbetar med är att binda Entry.BackgroundColor
egenskapen till dataobjektets PasswordStrength
egenskap, vilket är en Strength
uppräkning.
<Entry BackgroundColor="{Binding PasswordStrength} ... />
Uppräkningen Strength
måste konverteras till en Color
. Konverteraren måste därför utvärdera vilket värde som Strength
anges och returnera ett annat Color
. Följande kod visar den här konverteringen:
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();
}
Nu ska vi gå in på den här koden:
- Metoden
Convert
har fyra parametrar. Du kan vanligtvis ignorera de två sista parametrarna om du inte har en specifik anledning att använda dem. - Parametern
value
innehåller det inkommande värdet. I det här exemplet är det ettStrength
uppräkningsvärde. - Parametern
targetType
ignoreras. Men du kan använda den här parametern för att verifiera att den typ av egenskap som konverteraren används med är enColor
. Detta utelämnas i det här exemplet för enkelhetens skull. - Ett växeluttryck används för att returnera en annan färg baserat på
Strength
värdet.
Använda konverteraren i XAML
När konverterarklassen har skapats måste du skapa en instans av den och referera till den i bindningen. Standardsättet för att instansiera konverteraren finns i rotelementets resursordlista.
Mappa först ett XML-namnområde till .NET-namnområdet som innehåller konverteraren. I följande kodexempel cvt
mappar XML-namnområdet till MyProject.Converters
.NET-namnområdet:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:cvt="clr-namespace:MyProject.Converters"
...
Skapa sedan en instans i 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>
Nu finns en instans av konverteraren i resursordlistan med nyckeln StrengthToColorConverter
, som råkar vara samma namn som typen. Detta är ett typiskt sätt att namnge konverterare, eftersom du vanligtvis bara har en enda konverterare som du återanvänder i hela XAML. Om du av någon anledning behöver flera konverterarinstanser måste nycklarna vara olika mellan dem.
Slutligen refererar du till konverteraren på bindningen. Eftersom konverteraren finns i en resursordlista använder du markeringstillägget {StaticResource}
för att referera till det. Konverteraren tilldelas till bindningsegenskapen Converter
:
<Entry BackgroundColor="{Binding PasswordStrength, Converter={StaticResource StrengthToColorConverter}}" ... />