This article is currently in the process of being translated into Ukrainian (~95% done).
Перетворення значень за допомогою IValueConverter
Поки що ми використовували деякі прості види прив'язки даних, де властивість відправки та отримання була завжди сумісною. Однак, ви можете потрапити в ситуації коли вам потрібно використовувати зв'язане значення одного типу і потім представити його дещо інакше.
Коли потрібно використовувати value converter
Конвертори значень доволі часто використовуються з прив'язками даних. Ось деякі базові приклади:
- У вас є числове значення, але ви хочете показати нульові значення одним способом, а додатні числа - іншим способом.
- Ви хочете вибрати значення елементу CheckBox основане на значенні, але значення являє собою строку "так" або "ні" замість булевого значення.
- Ви маєте розмір файлу в байтах, але хочете представити його в байтах, кілобайтах, мегабайтах чи гігабайтах в залежності від того наскільки великий файл.
Це були деякі з простих варіантів застосування, але їх значно більше. Наприклад, ви можете хотіти активувати CheckBox елемент з булевим типом значення, але хочете щоб це значення було змінене місцями, тобто коли CheckBox елемент = checked, його значення буде false і навпаки, якщо не checked - true. Ви можете навіть використати конвертер для генерації зображення для властивості ImageSource, основане на значенні кольору, тобто -зелений знак - істина, червоний знак для хибності - можливості практично безмежні!
Для випадків як цей, можна використовувати конвертор значень. Ці класи, які реалізують IValueConverter interface, будуть діяти в ролі посередника і перекладати значення між джерелом та призначення(кінцевим типом). То ж в багатьох ситуаціях коли вам потрібно трансформувати значення перед тим як воно потрапить в потрібне місце призначення або повернеться назад в початкову точку, вам скоріш за все потрібно використовувати конвертор.
Реалізація простого перетворення значень
Як вже було зазначено, конвертор значень WPF потребує реалізації інтерфейсу IValueConverter, або в якості альтернативи, інтерфейсу IMultiValueConverter(пізніше буде більше про нього). Обидва інтерфейси потребують від вас реалізації всього двох методів: Convert() та ConvertBack(). Судячи з назв, ці методи будуть використовуватись для конвертації значень у потрібний вихідний формат і також для зворотної конвертації значення.
Давайте реалізуємо простий конвертор який приймає строку в якості вхідного параметру і повертає строку в якості булевого значення і це ж саме навпаки. Якщо ви новачок в WPF, а скоріш так і є виходячи з того що ви читаєте цю статтю, тоді вам мабуть не відомі всі концепти які використовуються в даному прикладі, але не переймайтесь, про них поговоримо після прикладів з кодом:
<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";
}
}
}
Code-behind
Що ж, давайте почнемо з самого початку а потім попрацюємо над прикладом. Ми реалізували конвертор у файлі Code-behind з назвою YesNoToBooleanConverter. Як вже було сказано, він лише реалізує два обов'язкові методи, з назвами Convert() та ConvertBack(). Convert() метод передбачає що він отримає строку в якості вхідного параметру(параметр value) і потім конвертує її в булеве значення - істина або хиба(true або false), з запасним значенням false. Щоб було веселіше, я додав можливість робити конвертацію з французьких слів також.
ConvertBack() метод очевидно робить зворотне: Він передбачає значення вхідного параметру з булевим типом даних і потім повертає з методу слово англійською - "yes" або "no" і в разі помилки з значенням "no".
Ви можете здивуватись стосовно додаткових параметрів які ці методи можуть приймати, але вони не потрібні в цьому прикладі. Ми їх використаємо в одному з наступних розділів, де про них буде пояснення.
XAML
В XAML частині програми, ми почнемо з оголошення екземпляру нашого конвертера в якості ресурсу для вікна. Ми також будемо мати TextBox та декілька TextBlock елементів а також CheckBox елемент і це якраз те місце де найцікавіші речі відбуваються: Ми прив'яжемо значення елементу TextBox до TextBlock і CheckBox елементу, і використовуючи властивість Convertor разом з посиланням на наш власний конвертор, ми будемо жонглювати значеннями вперед і назад між строковим значенням і булевим, в залежності від того яке потрібне.
Якщо ви спробуєте запустити даний приклад, ви зможете змінити значення в двох місцях: Написавши - "yes" в елементі TextBox(або будь яке інше значення, якщо хочете в результаті отримати - false) або виділити CheckBox. Не має значення що ви робите, зміна буде відображена на іншому елементі так само як і в TextBlock елементі.
Summary
Це був приклад простого конвертора значень, зроблено трохи довше ніж потрібно, в цілях ілюстрації. В наступному розділі ми розглянемо більш складний приклад, але перед тим як піти і написати власний конвертор, можливо вам захочеться глянути чи WPF вже включає конвертор для таких цілей. На момент написання, існує більше 20 вбудованих конвертерів, якими ви можете скористатися, але вам потрібно знати їх назву. Я знайшов цей список, який може стати вам у нагоді: http://stackoverflow.com/questions/505397/built-in-wpf-ivalueconverters