Powiązanie danych z niezgodnymi typami
Czasami używane dane nie są zgodne z typem danych właściwości kontrolki wyświetlającej dane. Na przykład możesz mieć wartość pieniężną przechowywaną decimal
w typie, który ma być wyświetlany w kontrolce Label
sformatowanej jako waluta. Bardziej skomplikowanym przykładem może być aplikacja pogodowa przedstawiona w module. Obraz ma być wyświetlany na podstawie wartości wyliczenia lub Cloudy
prognozy Sunny
pogody, ale nie można powiązać wartości wyliczenia źródła z właściwością obrazu obiektu docelowego. W tej lekcji przedstawiono sposoby konwertowania danych.
Formatowanie ciągu
Typowa niezgodność typów to typ wewnętrzny, który ma być wyświetlany jako sformatowany ciąg. Podobnie jak w przypadku, gdy chcesz wyświetlić części DateTime
wartości lub chcesz sformatować typ jako walutę decimal
.
Załóżmy, że chcesz wyświetlić kwotę należną na rachunku i masz tę właściwość w obiekcie danych:
public decimal BillAmount { get; set; }
Kwota należna wynosi 22,0304. Możesz użyć dwóch kontrolek etykiet, aby wyświetlić tekst i kwotę dolara, jak pokazano w poniższym fragmencie kodu:
<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>
Spowoduje to wyprowadzenie ciągu do interfejsu użytkownika, który wygląda następująco: You owe 22.0304 to the bank
, ale brakuje symbolu waluty i może być zbyt wiele lub zbyt mało miejsc dziesiętnych na podstawie waluty lokalnej. Zwykle wartość jest przetwarzana jako ciąg z specyfikatorem formatu "C" (lub waluty) w kodzie, w następujący sposób:
string formattedBillAmount = string.Format("{0:C}", BillAmount);
Jednak aby używać formatowania w powiązaniu danych, musisz mieć obiekt danych, aby zapewnić ten sformatowany ciąg jako inną właściwość lub przechwycić go jakoś i sformatować samodzielnie. Na szczęście powiązania MAUI platformy .NET umożliwiają formatowanie ciągów za StringFormat
pomocą właściwości powiązania. Ciąg formatu jest zgodny z tymi samymi regułami co String.Format
metoda. Ujmij ciąg formatu w pojedynczych cudzysłowach, aby analizator XAML nie był mylony przez nawiasy klamrowe. Parametr 0
formatu ciągu to wartość właściwości przetworzona przez powiązanie.
<Label Text="{Binding BillAmount, StringFormat='You owe {0:C} to the bank'}" />
Rozważmy następujący kod XAML, który pokazuje, jak używać BillAmount
obu sposobów:
<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>
Na poniższej ilustracji przedstawiono dane wyjściowe XAML generowane na ekranie:
Język XAML używający StringFormat
właściwości powiązania jest prostszy niż inny kod XAML i masz dostęp do elementu . Zaawansowany system formatowania ciągów platformy NET.
Konwersja typu niestandardowego
StringFormat
Właściwość powiązania jest wygodna podczas wyświetlania wartości jako ciągu, ale nie wtedy, gdy chcesz przekonwertować coś takiego jak lub Color
Image
z innego typu. W takich przypadkach należy napisać niestandardowy kod konwersji.
Załóżmy, że monitujesz użytkownika o wybranie hasła i chcesz użyć koloru w interfejsie użytkownika, aby wskazać siłę hasła. Istnieją trzy poziomy siły: słaby, dobry, silny. Siła zależy od liczby znaków w haśle. Aby przekazać użytkownikowi natychmiastową opinię na temat siły hasła, chcesz, aby tło Entry
kontrolki zawierającej hasło zmieniło się na podstawie siły. Na poniższej ilustracji przedstawiono te trzy poziomy siły: słabe, dobre i silne.
Spośród trzech kontrolek wprowadzania na zrzucie ekranu pierwszy zawiera cztery znaki i zawiera czerwone tło. Drugi zawiera dziewięć znaków i zawiera żółte tło. Ostatnia kontrolka wpisu ma 15 znaków i zawiera niebieskie tło.
Te poziomy są przypisywane do Strength
wyliczenia:
private enum Strength
{
Weak,
Good,
Strong
}
Obiekt danych jest przypisywany jako obiekt strony BindingContext
, który zawiera siłę hasła z właściwością PasswordStrength
. Ponieważ użytkownik wpisuje hasło, PasswordStrength
właściwość jest zmieniana zgodnie z długością hasła. Ponieważ obiekt danych zawiera PasswordStrength
właściwość , należy powiązać właściwość z BackgroundColor
kontrolką Entry
:
<Entry BackgroundColor="{Binding PasswordStrength} ... />
Istnieje jednak problem. Parametr PasswordStrength
jest typu Strength
, a BackgroundColor
element to Color
. Te typy nie są ze sobą zgodne. Program .NET MAUI umożliwia rozwiązywanie problemów z niezgodnością typów, właściwością powiązania Converter
.
Konwerter powiązań robi tylko to, co jego nazwa mówi, konwertuje między źródłem powiązania a elementem docelowym. Konwertery są implementowane za pośrednictwem interfejsu IValueConverter
.
Implementowanie elementu IValueConverter
Logikę konwersji można utworzyć w klasie, która implementuje IValueConverter
interfejs. Zazwyczaj nazwy tych klas kończą się nazwą Converter
, aby jej przeznaczenie było jasne.
Interfejs IValueConverter
definiuje dwie metody:
Convert
— konwertuje właściwość źródła powiązania na właściwość interfejsu użytkownika obiektu docelowego powiązania.ConvertBack
— konwertuje właściwość interfejsu użytkownika elementu docelowego powiązania z powrotem na właściwość źródła powiązania.Ta metoda jest rzadko używana i nie jest używana w tym scenariuszu. Większość konwerterów zgłasza wartość ,
NotSupportedException
aby wskazać, że ta konwersja nie jest obsługiwana.
Oto kontrakt interfejsu:
public interface IValueConverter
{
object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture);
object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture);
}
Pamiętaj, że scenariusz, z którym pracujemy, wiąże Entry.BackgroundColor
właściwość z właściwością obiektu PasswordStrength
danych, która jest wyliczeniem Strength
.
<Entry BackgroundColor="{Binding PasswordStrength} ... />
Wyliczenie Strength
musi zostać przekonwertowane na .Color
Dlatego konwerter musi ocenić, która Strength
wartość jest podana, i zwrócić inną Color
wartość . Poniższy kod demonstruje tę konwersję:
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();
}
Przeanalizujmy ten kod:
- Metoda
Convert
ma cztery parametry. Można zazwyczaj odrzucić dwa ostatnie parametry, chyba że masz określony powód do ich użycia. - Parametr
value
zawiera wartość przychodzącą. W tym przykładzieStrength
jest to wartość wyliczenia. - Parametr
targetType
jest ignorowany. Można jednak użyć tego parametru, aby sprawdzić, czy typ właściwości, z którą jest używany konwerter, toColor
. W tym przykładzie pominięto to dla uproszczenia. - Wyrażenie przełącznika służy do zwracania innego koloru na
Strength
podstawie wartości.
Używanie konwertera w języku XAML
Po utworzeniu klasy konwertera należy utworzyć wystąpienie i odwołać się do niego w powiązaniu. Standardowy sposób tworzenia wystąpienia konwertera znajduje się w słowniku zasobów elementu głównego.
Najpierw zamapuj przestrzeń nazw XML na przestrzeń nazw platformy .NET zawierającą konwerter. W poniższym przykładzie cvt
kodu przestrzeń nazw XML mapuje się na przestrzeń nazw platformy MyProject.Converters
.NET:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:cvt="clr-namespace:MyProject.Converters"
...
Następnie utwórz wystąpienie w pliku 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>
Teraz wystąpienie konwertera znajduje się w słowniku zasobów z kluczem StrengthToColorConverter
, który ma taką samą nazwę jak typ. Jest to typowy sposób nazewnictwa konwerterów, ponieważ zwykle masz tylko jeden konwerter używany ponownie w całym języku XAML. Jeśli z jakiegoś powodu wymagane jest wiele wystąpień konwertera, klucze muszą być różne między nimi.
Na koniec odwołaj się do konwertera w powiązaniu. Ponieważ konwerter znajduje się w słowniku zasobów, należy użyć {StaticResource}
rozszerzenia znaczników, aby się do niego odwoływać. Konwerter jest przypisywany Converter
do właściwości powiązania:
<Entry BackgroundColor="{Binding PasswordStrength, Converter={StaticResource StrengthToColorConverter}}" ... />