Конвертеры значений (value converter) позволяют преобразовать значения, приходящие от источника привязки, к тому типу, который понятен приемнику привязки. Не всегда два связываемых привязкой свойства могут иметь совместимые типы. И в этом случае как раз и нужен конвертер значений.
Возьмем, к примеру, привязку элемента DatePicker к TextBlock. Допустим, мы хотим вывести выбранную дату в текстовое поле. Зная основы привязки, мы бы сделали так:
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <DatePicker x:Name="calendar" /> <TextBlock Text="{Binding ElementName=calendar, Path=Date}" /> </StackPanel>
Однако практического результата мы бы не получили:
Все потому что свойство Date объекта DatePicker представляет объект DateTimeOffset, и система просто не знает, как его преобразовать в строку. В этом случае нам как раз понадобится конвертер значений.
Теперь добавим в проект следующий класс:
using System; using Windows.UI.Xaml.Data; public class DateTimeOffsetToStringConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { DateTimeOffset sourceTime = (DateTimeOffset)value; DateTime targetTime = sourceTime.DateTime; return targetTime.ToString("dd.MM.yyyy"); } public object ConvertBack(object value, Type targetType, object parameter, string language) { DateTimeOffset resultTime = DateTime.Parse(value.ToString()); return resultTime; } }
Конвертер значений должен реализовать интерфейс Windows.UI.Xaml.Data.IValueConverter. В нем определяюся два метода:
Convert()
(преобразует значение от источника привязки в тип, понятный для приемника привязки) и ConvertBack()
(выполняет противоположную операцию). Оба метода принимают следующие параметры:
object value
: значение, которое надо преобразовать
Type targetType
: тип, к которому надо преобразовать значение value
object parameter
: вспомогательный параметр привязки
string language
: языковой код текущей культуры, например, "en-US"
В нашем конвертере значений метод Convert
возвращает строковое представление даты в формате "dd.MM.yyyy". То есть мы ожидаем, что в
качестве параметра value будет передаваться объект DateTimeOffset.
Метод ConvertBack
выполняет обратное преобразование - из строки в DateTimeOffset.
Используем наш конвертер в xaml:
<Page x:Class="BindingApp.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:BindingApp" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Page.Resources> <local:DateTimeOffsetToStringConverter x:Key="myDateConverter" /> </Page.Resources> <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <DatePicker x:Name="calendar" /> <TextBlock Text="{Binding ElementName=calendar, Path =Date,Converter={StaticResource myDateConverter}}" /> </StackPanel> </Page>
Здесь объект конвертера значений задан как ресурс. Чтобы применить этот конвертер в конструкции привязки используется параметр
Converter с ссылкой на ресурс: Converter={StaticResource myDateConverter}
И теперь текстовый блок будет выводить дату как и должен:
Кроме конвертера мы также можем использовать параметры ConverterParameter и ConverterLanguage.
В конвертере значений это соответственно параметры object parameter
и string language
. Применим их, изменим код конвертера:
public class DateTimeOffsetToStringConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { DateTimeOffset sourceTime = (DateTimeOffset)value; DateTime targetTime = sourceTime.DateTime; string result = targetTime.ToString("dd.MM.yyyy"); // проверяем язык if (language == "en-US") result = targetTime.ToString("MM-dd-yyyy"); // проверяем переданный параметр if (parameter!=null && parameter.ToString() == "full") result = "Сегодня: " + result; return result; } public object ConvertBack(object value, Type targetType, object parameter, string language) { DateTimeOffset resultTime = DateTime.Parse(value.ToString()); return resultTime; } }
В качестве параметра может передаваться любой объект. Если параметр в xaml не используется, то передается null. В данном случае мы проверяем, равен ли параметр строке "full", то есть мы ожидаем, что параметр будет передавать строковое значение. И если равен, то добавляем к дате строку "Сегодня". Также если язык имеет код "en-US", то возвращает дату в другом формате.
Для применения параметра изменим код xaml:
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <DatePicker x:Name="calendar" /> <TextBlock Text="{Binding ElementName=calendar, Path=Date, Converter={StaticResource myDateConverter}}" /> <TextBlock Text="{Binding ElementName=calendar, Path=Date, Converter={StaticResource myDateConverter}, ConverterParameter=full, ConverterLanguage=en-US}" /> </StackPanel>