This article has been localized into Polish by the community.
Konwersja wartości za pomocą IValueConverter
Do tej pory zastosowaliśmy kilka prostych powiązań, kiedy to typy danych wysyłanych i odbieranych były zawsze ze sobą kompatybilne. Jednak spotkasz się z wieloma przypadkami, gdy dane konkretnego typu trzeba będzie zaprezentować w nieco inny sposób.
Kiedy stosujemy konwerter wartości?
Konwertery wartości są bardzo często używane przy wiązaniu danych. Oto kilka podstawowych przykładów:
- Masz wartość liczbową, ale chciałbyś pokazać wartość zero w jednych przypadkach, a liczby dodatnie w pozostałych
- Chciałbyś zaznaczyć CheckBox na podstawie wartości zmiennej, ale ta wartość jest tekstem np. "tak" lub "nie", a nie wartością typu Boolean (true/false).
- Masz wielkość pliku wyrażoną w bajtach, ale chciałbyś ją pokazać w bajtach, kilobajtach, megabajtach lub gigabajtach, w zależności od jej wielkości
Jest to kilka prostych przypadków, ale może być ich zdecydowanie więcej. Na przykład chcesz ustawić zaznaczenie kontrolki CheckBox na podstawie zmiennej typu Boolean, ale na odwrót - to znaczy chciałbyś, aby CheckBox był zaznaczony, gdy zmienna jest równa "false", a niezaznaczony, gdy zmienna jest równa "true". Mógłbyś nawet wykorzystać konwerter do wygenerowania obrazka i ustawienia go w ImageSource w zależności od wartości zmiennej. Na przykład sygnał zielony dla wartości "true" i czerwony dla "false". Możliwości są praktycznie nieograniczone!
W takich przypadkach możesz zastosować konwerter wartości. The niewielkie klasy, które implementują interfejs IValueConverter, będą działać jak pośrednicy i tłumaczyć wartości między źródłem a miejscem docelowym. We jakichkolwiek przypadkach, gdy potrzebujesz dokonać transformacji danych w jedną lub w drugą stronę - najprawdopodobniej potrzebujesz konwertera.
Implementacja prostego konwertera wartości
Jak wspomniano wcześniej - konwerter wartości WPF wymaga zaimplementowania interfejsu IValueConverter lub alternatywnie interfejsu IMultiValueConverter (więcej o nim powiemy później). Oba interfejsy wymagają tylko zaimplementowania dwóch metod: Convert() i ConvertBack(). Jak sama nazwa wskazuje, te metody będą używane do konwersji wartości do docelowego formatu oraz w drugą stronę - do formatu źródłowego.
Spróbujmy teraz zaimplementować prosty konwerter, który przekształci wartość tekstową na wartość Boolean i odwrotnie. Jeśli jesteś początkujący w WPF (a pewnie tak jest, skoro czytasz ten kurs) możesz nie znać wszystkich pojęć użytych w tym przykładzie, ale nie martw się - wszystkie zostaną wyjaśnione w kolejnej części za kodem:
<Window x:Class="WpfTutorialSamples.DataBinding.ConverterSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfTutorialSamples.DataBinding"
Title="ConverterSample" Height="140" Width="250">
<Window.Resources>
<local:YesNoToBooleanConverter x:Key="YesNoToBooleanConverter" />
</Window.Resources>
<StackPanel Margin="10">
<TextBox Name="txtValue" />
<WrapPanel Margin="0,10">
<TextBlock Text="Current value is: " />
<TextBlock Text="{Binding ElementName=txtValue, Path=Text, Converter={StaticResource YesNoToBooleanConverter}}"></TextBlock>
</WrapPanel>
<CheckBox IsChecked="{Binding ElementName=txtValue, Path=Text, Converter={StaticResource YesNoToBooleanConverter}}" Content="Yes" />
</StackPanel>
</Window>
using System;
using System.Windows;
using System.Windows.Data;
namespace WpfTutorialSamples.DataBinding
{
public partial class ConverterSample : Window
{
public ConverterSample()
{
InitializeComponent();
}
}
public class YesNoToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
switch(value.ToString().ToLower())
{
case "yes":
case "oui":
return true;
case "no":
case "non":
return false;
}
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if(value is bool)
{
if((bool)value == true)
return "yes";
else
return "no";
}
return "no";
}
}
}
Kod C# (Code-behind)
Przeanalizujmy teraz kod z przykładu. Zaimplementowaliśmy konwerter wartości w klasie YesNoToBooleanConverter, która ma dwie metody: Convert() i ConvertBack(), wymagane przez interfejs IValueConverter. Metoda Convert() zakłada, że na wejściu otrzyma zmienną typu string (parametr o nazwie value) i konwertuje ją na typ Boolean ("true" lub "false") z domyślną wartością równą "false". Dla zabawy dodałem również konwersję z języka francuskiego.
Oczywiście metoda ConvertBack() wykonuje pracę odwrotną: zakłada ona, że otrzyma w parametrze wejściowym wartość typu Boolean i zwróci angielskie słowo "yes" lub "no", z domyślną wartością równą "no".
Możesz się zastanawiać, do czego służą pozostałe parametry w tych dwóch metodach, ale w tym przykładzie nie są one potrzebne. Wykorzystamy je w kolejnych rozdziałach, gdzie zostaną dokładnie omówione.
XAML
W części XAML programu zaczynamy od deklaracji instancji naszego konwertera jako zasoby okna (Window.Resources). Następnie mamy kontrolkę TextBox, jedną parę kontrolek TextBlock i jeden CheckBox. I to jest to miejsce, w którym dzieją się najciekawsze rzeczy: łączymy tu zawartość kontrolki TextBox z kontrolką TextBlock oraz z kontrolką CheckBox z wykorzystaniem właściwości "Converter" i referencji do naszego konwertera. Dzięki temu wartości tekstowe będą zamieniane na logiczne i z powrotem, w zależności co jest potrzebne.
Po uruchomieniu tego przykładu będziesz mieć możliwość zmiany wartości w dwóch miejscach: wpisując "yes" do kontrolki TextBox, jeśli chcesz otrzymać po konwersji "true" lub jakiekolwiek inne słowo, jeśli chcesz otrzymać "false" - lub przez zmianę wyboru w kontrolce CheckBox. W zależności, którą kontrolkę zmienisz, będzie to miało wpływ na wartości w pozostałych kontrolkach.
Podsumowanie
Jest to przykład na proste zastosowanie konwertera wartości. Przykład jest nieco dłuższy, niż było to zamierzone, ale wszystko w celu lepszego wyjaśnienia tematu. W kolejnym rozdziale zajmiemy się bardziej rozbudowanym przykładem, ale zanim zasiądziesz do napisania własnego konwertera, poszukaj czy przypadkiem WPF już takiego nie zawiera. W chwili pisania tego tekstu w WPF jest ponad 20 wbudowanych konwerterów, które możesz wykorzystać, ale musisz poznać ich nazwy. Znalazłem następująca listę, która może ci się przydać: http://stackoverflow.com/questions/505397/built-in-wpf-ivalueconverters