Blog (220)
Komentarze (4k)
Recenzje (1)
@djfoxerTworzymy własny ValueConverter, czyli najbardziej przydatny obiekt w bindowaniu danych do widoku (XAML/C#)

Tworzymy własny ValueConverter, czyli najbardziej przydatny obiekt w bindowaniu danych do widoku (XAML/C#)

01.06.2016 01:57

Zapewne tworząc aplikacje w WPF czy UWP natknęliście się na to, że właściwość w modelu (ViewModelu) wymagała konwersja na inny typ lub inną wartość, aby móc jej użyć na widoku. Tworzenie jednak dodatkowych właściwości jest nieefektywne i zbędne.

Z pocą przychodzi interfejs IValueConverter, który konwertuje jedne dane na drugie, bez konieczność rozszerzania obiektu. W moim przypadku musiałem przekwaterować status notyfikacji NotificationStatus (New, Old, Unknown) na Opacity (nieprzezroczystość).

Na widoku nowe powiadomienia nie są przezroczyste, zaś stare mają przezroczystość ustawioną na 0.5. Efekt jest następujący:

593514

Oczywiście najbardziej używanym konwerterem jest: Bool <=> Visibility, czyli mając zmienną o typu Bool(true/false), chcemy sterować widocznością elementu (Visibility.Visible/Visibility.Collapsed).Przejdźmy jednak do naszego przykładu.

Zamiast tworzyć nową właściwość, szybko tworzymy klasę implementującą interfejs IValueConverter.


public sealed class StatusToOpacityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        NotificationStatus status = (NotificationStatus)value;
        if (status == NotificationStatus.New)
        {
            return 1;
        }
        else
        {
            return 0.5;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

Interfejs IValueConverter wymaga implementacji dwóch metod: Convert i ConvertBack.Pierwsza z nich implementuje konwersję danych z obiektu na dane niezbędne do użycia na widoku, zaś druga robi to w odwrotną stronę.

W naszym przypadku zadanie jest proste. Powiadomienie ze statusem NotificationStatus.New nie może być przezroczyste, zaś notyfikacje z innymi statusami mają otrzymać przezroczystość 0.5. Zmienna value jest zawsze typu NotificationStatus, więc bez dodatkowej zabawy rzutujemy ją na ten typ i zwracamy int określający przezroczystość.

Możemy skorzystać również ze zmiennej targetType, z typem zmiennej wynikowej. Dodatkowo parameter może zawierać dodatkowe informacje przesłane do konwertera z widoku. Ważnym parametrem jest także zmienna language, która określa język aplikacji w chwili konwersji, do wykorzystania, gdy konwersja zależna jest od używanego języka (np. zamiana daty na string).

W drugą stronę konwersja przebiega podobnie z tym, że dane wejściowe i wyjściowe są zamienione. W omawianym przypadku na wejściu mielibyśmy zmienną int, a typem wynikowym byłby NotificationStatus.

Jednakże nie jest to nam potrzebne, gdyż łączenie (bindowanie) w tym przypadku obiektu (z danymi) z widokiem odbywa się w jedną stronę (one-way binding).

Na widoku, czyli w pliku XAML, konwertera użyjemy w następujący sposób:


<Grid
        Opacity="{
        Binding Status, 
        Converter={StaticResource StatusToOpacityConverter},
        Mode=OneWay
        }" 
                      
        >(...)</Grid>

Oczywiście obiekt przekazany do widoku ma właściwość Status o typie NotificationStatus.

Na końcu pamiętajmy jeszcze o rejestracji StatusToOpacityConverter w App.xaml:


<Application
    (...)
    xmlns:helpers="using:djfoxer.dp.notification.App.Helpers">
    <Application.Resources>
        (...)
        <helpers:StatusToOpacityConverter  x:Key="StatusToVisibilityConverter"  />
    </Application.Resources>
</Application>
DePesza dostępna jest w markecie Windows 10 (desktop i mobile). Bezpośredni link: DePesza.
Aktualne źródła można znaleźć na GitHub pod adresem: https://github.com/djfoxer/dp.notification
Wybrane dla Ciebie
Komentarze (4)