Привязка позоляет связать два свойства, которые совпадают по типу данных. Например, свойство Text у класса Entry и свойство Text класса Label представляют тип string. Поэтому тут привязка проходит без проблем. Но в других случаях тип связанных свойств может отличаться. В большинстве случаев инфраструктра Xamarin сама знает, как конвертировать данные простейших типов. Однако в каких-то ситуациях этого оказывается недостаточно, особенно когда необходимо применить к значению привязки дополнительное форматирование.
Например, пусть у нас элемент Label привязан к элементу DatePicker и выводит выбранную дату. По умолчанию дата выводится в формате "MM/dd/yyyy hh:mm:ss". Это не очень удобный формат. Возможно, мы захотим использовать совсем другие форматы.
Для преобразования одного значения к другому в процессе привязки используются пециальные классы - конвертеры значений. К примеру, добавим в наш проект новый класс конвертера значений:
using System; using System.Globalization; using Xamarin.Forms; namespace HelloApp { public class DateTimeToLocalDateConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return ((DateTime)value).ToString("dd.MM.yyyy"); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return DateTime.Now.ToString("dd.MM.yyyy"); } } }
Прежде всего класс конвертера значений должен реализовать интерфейс IValueConverter. Этот интерфейс определяет два
метода: Convert()
, который преобразует пришедшее от привязки значение в тот тип, который понимается приемником привязки, и
ConvertBack()
, который выполняет противоположную операцию.
Оба метода принимают четыре параметра:
object value
: значение, которое надо преобразовать
Type targetType
: тип, к которому надо преобразовать значение value
object parameter
: вспомогательный параметр
CultureInfo culture
: текущая культура приложения
В примере выше метод Convert возвращает дату в виде строки в формате "dd.MM.yyyy". То есть мы ожидаем, что в качесве параметра value будет передаваться объект DateTime.
Метод ConvertBack в данном случае не имеет значения, и поэтому он просто возвращает строковое представление текущей даты.
Теперь применим этот конвертер в xaml:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:HelloApp;assembly=HelloApp" x:Class="HelloApp.MainPage"> <ContentPage.Resources> <ResourceDictionary> <local:DateTimeToLocalDateConverter x:Key="dateConverter" /> </ResourceDictionary> </ContentPage.Resources> <StackLayout> <Label Text="{Binding Source={x:Reference Name=datePicker}, Path=Date}" /> <Label Text="{Binding Source={x:Reference Name=datePicker}, Path=Date, Converter={StaticResource dateConverter}}" /> <DatePicker x:Name="datePicker" Format="D" /> </StackLayout> </ContentPage>
Так как класс конвертера располагается в пространстве имен текущего проекта, то, чтобы класс был доступен в xaml, надо подключить текущее пространство имен.
xmlns:local="clr-namespace:HelloApp;assembly=HelloApp"
В моем случае пространством имен является HelloApp, и оно проецируется на суффикс local
Затем в ресурсах создается объект привязки с ключом dateConverter
.
И далее в самом выражении привязки мы подключем данный ресурс в качестве конвертера:
Converter={StaticResource dateConverter}
При этом здесь привязка идет к элементу выбора даты для двух объектов Label. Но только второй объект применяет конвертер:
Возьмем другой случай. Допустим, нам надо привязать цвет метки к вводимому в текстовое поле значение. Для этого определим следующий конвертер:
using System; using System.Globalization; using Xamarin.Forms; namespace HelloApp { public class StringToColorConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { Color color = Color.White; string colorStr = value.ToString().ToLower(); switch(colorStr) { case "красный": color = Color.Red; break; case "желтый": color = Color.Yellow; break; case "зеленый": color = Color.Green; break; case "синий": color = Color.Blue; break; } return color; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return Color.White; } } }
Если вводится определенная строка, то конвертер возвращает определенный цвет. Теперь применим этот конвертер в XAML:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:HelloApp;assembly=HelloApp" x:Class="HelloApp.MainPage"> <ContentPage.Resources> <ResourceDictionary> <local:StringToColorConverter x:Key="colorConverter" /> </ResourceDictionary> </ContentPage.Resources> <StackLayout> <Entry x:Name="entry1" Text="Red" /> <Label x:Name="label1" Text="Xamarin" TextColor="{Binding Source={x:Reference Name=entry1}, Converter={StaticResource colorConverter}, Path=Text}" /> </StackLayout> </ContentPage>