Powiązanie danych z niezgodnymi typami
- 10 min
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ą w typie decimal
, którą chcesz wyświetlić na kontrolce Label
, sformatowaną jako waluta. Bardziej skomplikowanym przykładem może być aplikacja pogodowa przedstawiona w module. Obraz powinien być wyświetlany na podstawie wartości wyliczenia Sunny
lub Cloudy
związanej z prognozą pogody, ale nie można powiązać wartości wyliczenia źródła z właściwością obrazu celu. 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 wtedy, gdy chcesz wyświetlić części wartości DateTime
albo sformatować typ decimal
jako walutę.
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 należy przetworzyć wartość 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żyć formatowania w powiązaniu danych, musisz albo sprawić, by obiekt danych dostarczył ten sformatowany ciąg jako inną właściwość, albo przechwycić go w jakiś sposób i sformatować samodzielnie. Na szczęście powiązania .NET MAUI umożliwiają formatowanie ciągów za pomocą właściwości powiązań StringFormat
. 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 jest wartością właściwości procesów powiązania.
<Label Text="{Binding BillAmount, StringFormat='You owe {0:C} to the bank'}" />
Proszę potencjalnie rozważyć następujący kod XAML, który demonstruje wyświetlanie BillAmount
na dwa sposoby:
<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 zaawansowanego systemu formatowania ciągów platformy .NET.
Konwersja typu niestandardowego
Właściwość StringFormat
jest wygodna podczas wyświetlania wartości jako ciągu, ale nie wtedy, gdy chcesz przekonwertować coś takiego jak Color
lub 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 pokazanych na zrzucie ekranu, pierwsza zawiera cztery znaki i ma 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 dzięki właściwości PasswordStrength
określa siłę hasła. 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
jest Color
. Te typy nie są ze sobą zgodne. Program .NET MAUI daje możliwość naprawy problemów z niezgodnością typów, korzystając z 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
Tworzysz logikę konwersji w klasie, która implementuje interfejs IValueConverter
. 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, za pomocą którego 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
, więc 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 wartością wyliczenia. - Parametr
targetType
jest ignorowany, ale można 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 zwraca inny kolor na podstawie wartości
Strength
.
Używanie konwertera w języku XAML
Po utworzeniu klasy konwertera, należy utworzyć jej wystąpienie i odwołać się do niego w powiązaniu. Standardowy sposób inicjowania konwertera to umieszczenie go 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 kodu przestrzeń nazw XML cvt
jest mapowana na przestrzeń nazw .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"
...
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 instancja 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 na połączeniu. 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 do właściwości powiązania: Converter
<Entry BackgroundColor="{Binding PasswordStrength, Converter={StaticResource StrengthToColorConverter}}" ... />