Главная » Silverlight » Преобразование данных

0

При обычном связывании информация передается от источника к целевому объек­ту без изменений. Такое поведение кажется логичным, но оно не всегда желательно. Иногда в источнике используется низкоуровневое представление информации, которое нельзя выводить непосредственно в пользовательский интерфейс. Например, желатель­но заменить числовые коды удобочитаемыми строками, отсечь "длинные хвосты" деся­тичных дробей, вывести дату в удобном формате и т.п. Во всех этих случаях необходим способ преобразования значений. При двустороннем связывании тоже необходимо пре­образование. Пользовательские данные должны быть преобразованы в формат, пригод­ный для хранения в объекте данных.

Платформа Silverlight позволяет выполнять преобразование в обоих направлениях с помощью классов преобразователей значений. Преобразователь значений обрабатывает данные источника непосредственно перед выводом в целевом элементе и (в случае дву­стороннего связывания) непосредственно перед записью значения обратно в источник.

Преобразователи значений — полезные компоненты системы связывания данных. Ниже приведены способы их использования.

•       Для создания строкового представления данных. Например, можно преобра­зовать число в строку валюты. Это наиболее очевидный пример использования преобразователей, но далеко не единственный.

•       Для создания специфических типов объектов Silverlight. Например, можно прочитать блок двоичных данных и создать объект Bitmaplmage, связанный с элементом Image.

•       Для условного изменения свойства элемента на основе значений связанных данных. Например, преобразователь может изменить цвет фона элемента при получении значения в заданном диапазоне.

В следующих разделах рассматривается каждый из этих подходов.

Форматирование строк с помощью преобразователей значений

[1] Создание класса, реализующего интерфейс IValueConverter (он находится в про­странстве имен System. Windows. Data). Этот класс нужно разместить не в службе, а в проекте Silverlight, в котором выполняется преобразование.

Преобразователи — совершенный инструмент форматирования чисел, которые нуж­но вывести как текст. В качестве примера рассмотрим свойство Product.UnitCost, со­держащее цену единицы продукта. Оно хранится как десятичное число. В результате, в текстовом поле выводится, например, такое значение: 4 9. 9900. Оно содержит после десятичного разделителя больше цифр, чем нужно. Кроме того, в нем отсутствует сим­вол валюты. Поэтому желательно отобразить более интуитивное представление $4 9.99, как показано на рис. 16.9.

Рис. 16.9. Вывод отформатированного денежного значения Создание преобразователя значений состоит из трех этапов.

2.     Реализация метода Convert (), который преобразует данные из формата источ­ника в целевой формат.

3.     Реализация метода ConvertBack (), который преобразует данные из целевого формата в формат источника.

На рис. 16.10 показана работа преобразователя значений.

Рис. 16.10. Преобразование связанных данных

Для преобразования десятичного значения в денежное можно использовать метод Decimal. ToString (), задав денежный формат с помощью строки С.

string currencyText = decimalPrice.ToString("С");

В коде неявно используются региональные параметры, применяемые к текущему по­току. Если в операционной системе установлен регион English (United States), то применяется культура en-US и в качестве символа валюты выводится доллар ($). При установке другого региона выводится другой символ валюты. Чтобы установить опреде­ленный символ валюты (например, если нужно, чтобы всегда выводился доллар), задай­те культуру в перегруженной версии метода ToString ().

Culturelnfo culture = new Culturelnfo("en-US") ;

string currencyText = decimalPrice.ToString("C", culture);

і

Список всех строк форматирования можно найти в справочной системе Visual Studio. В табл. 16.3 и 16.4 приведены наиболее популярные форматы, используемые для чисел и дат.

Таблица 16.3. Форматирующие строки для числовых данных

Тип

Форматирующая строка

Пример

Денежный

с

$1,234.50; скобки обозначают отрицательное значение: ($1,234.50); символ валюты зависит от культуры

Научный

Е

1,234.50Е+004

Процентный

Р

45. 6%

Фиксированный десятичный

F?

Зависит от количества десятичных позиций после разделителя; формат F3 выводит строку 123.400, а формат F0 — строку 123

Таблица 16.4. Форматирующие строки для времени и даты

Тип

Форматирующая строка

Пример

Короткая дата

d

M/d/yyyy; например, 10/30/2009

Длинная дата

D

dddd, мммм dd, yyyy; например, Понедельник, Январь ЗО, 2009

Длинная дата и короткое время

f

dddd, ММММ dd, yyyy HH:mm aa; например, Понедельник, Январь ЗО, 2009 10:00 AM

Длинная дата и длинное время

F

ddd, ММММ dd, yyyy HH:mm:ss aa; например, Понедельник, Январь ЗО, 2009 10:00:23 AM

Сортируемый стандарт ISO

s

yyyy-MM-dd HH:mm:ss; например, 2009-01-30 10:00:23

Месяц и день

м

ММММ dd; например, Январь 30

Общий

G

M/d/yyyy HH:mm: ss aa (в зависимости от региона); например, 10/30/2009 10:00:23 AM

Преобразование выводимого формата обратно в формат числа — более коварная операция. Можно использовать методы Parse () и TryParse () типа Double, однако они обычно не могут справиться со строками, содержащими символ валюты. Одно из воз­можных решений состоит в применении перегруженной версии метода Parse () или TryParse, принимающей значение System.Globalization.NumberStyles. При значении NumberStyles. Any метод успешно удаляет символ валюты {если он присутствует).

Ниже приведен полный код преобразователя значений, обрабатывающего денежные значения (например, значения свойства Product.UnitCost).

public class PriceConverter : IValueConverter

{

public object Convert(object value, Type targetType,

object parameter, Culturelnfo culture)

{

double price = (double)value;

return price.ToString ("C", culture);

)

public object ConvertBack(object value, Type targetType,

object parameter, Culturelnfo culture)

{

string price = value.ToStringO ;

double result;

if (Double.TryParse(price, NumberStyles.Any, culture, out result))

{

return result;

}

return value;

}

}

Чтобы применить преобразователь, нужно добавить в проект используемый в раз­метке префикс пространства имен XML. Ниже приведен пример объявления пре-

фикса local. Предполагается, что преобразователь находится в пространстве имен

DataBinding.

xmlns:local="clr-namespace:DataBinding"

Обычно этот атрибут добавляют в открывающий дескриптор <UserControl>, рас­положенный в верхней части разметки.

Теперь несложно создать экземпляр класса PriceConverter в коллекции Resources страницы.

<OserControl.Resources> clocal:PriceConverter x:Key="PriceConverter">

</local:PriceConverter> </UserControl.Resources>

После этого можно указать на преобразователь в системе связывания с помощью ссылки StaticResource.

•CTextBox Margin="5" Grid.Row="2" Grid.Column="l" Text="{Binding UnitCost, Mode=TwoWay, Converter={StaticResource PriceConverter)}"> </TextBox>

Примечание. В отличие от WPF, в Silverlight нет интерфейса iMultiValueConverter. В результате преобразовывать можно только отдельные значения. Объединять значения (например, поля имени и фамилии) или выполнять вычисления (например, умножать цену единицы продукта на количество) нельзя.

Создание объектов с помощью преобразователя значений

Преобразователи значений незаменимы, когда нужно заполнить "пропасть" между форматом хранения данных в классах и форматом вывода этих же данных на стра­нице. Предположим, рисунок хранится в поле базы данных как двоичный массив. Двоичные данные несложно преобразовать в объект типа System.Windows .Media. Imaging.Bitmaplmage и сохранить в объекте данных. Однако такое решение крайне неудовлетворительное.

В результате преобразования в объект определенного типа теряется гибкость при­ложения. Часто необходимо иметь более одного представления графических данных, например, когда библиотека данных используется в приложениях Silverlight и Windows Fbrms (тогда необходим тип System.Drawing.Bitmap). В этом случае намного лучше хранить в объекте данных двоичную информацию, а затем преобразовать ее в объект Bitmaplmage с помощью преобразователя значений.

Совет. Для преобразования блока двоичных данных в изображение сначала создайте объект Bitmaplmage и запишите данные в поток MemoryStream. Затем вызовите метод Bitmaplmage. SetSource (), чтобы передать поток объекту Bitmaplmage.

Таблица Products базы данных Store содержит не двоичные рисунки, а столбец Productlmage, в котором находятся имена файлов с изображениями продуктов. Это до­полнительный повод отказаться от создания объектов изображений. Во-первых, изо­бражение может отсутствовать (в зависимости от того, где выполняется приложение). Во-вторых, не имеет смысла занимать оперативную память изображениями (объем каждого довольно большой), которые не будут выведены на экран.

Столбец Product Image содержит имя файла изображения, но не полный адрес URI. Преобразователь значений на основе поля Productlmage и адреса используемого сайта должен создать URI, указывающий на файл изображения. Корневой адрес URI хранится в пользовательском свойстве Root Uri, который по умолчанию указывает на корневую папку сайта.

Ниже приведен полный код класса ImagePathConverter, выполняющего преобразо­вание имени файла изображения в адрес URI.

public class ImagePathConverter : IValueConverter {

private string rootUri;

public string RootUri {

get { return rootUri; } set { rootUri = value; }

)

public ImagePathConverter()

{

string uri = HtmlPage.Document.DocumentUri.ToString();

// Удаление веб-страницы из текущего URI // для получения корневого URI rootUri = uri.Remove(uri.LastlndexOf (‘ /’), uri.Length – uri.LastlndexOf(‘/’));

}

public object Convert(object value, Type targetType, object parameter,

System.Globali zation.Culturelnfо culture)

{

string imagePath = RootUri + "/" + (string) value; return new Bitmaplmage(new Uri(imagePath));

}

public object ConvertBack(object value, Type targetType, object parameter,

System.Globalization.Culturelnf о culture)

(

// Изображения не редактируются, поэтому поддерживать // класс ConvertBack не нужно throw new NotSupportedException ();

}

}

Чтобы применить данный преобразователь, добавьте его в свойство Resources. Свойство RootUri не устанавливается, поэтому в классе ImagePathConverter по умол­чанию используется сайт текущего приложения.

<UserControl.Resources> clocal:ImagePathConverter x:Key="ImagePathConverter"> </local:ImagePathConverter> </UserControl.Resources>

Теперь несложно создать выражение связывания, в котором используется данный преобразователь значений.

<Image Margin="5" Grid.Row="2" Grid.Column="l" Stretch="None"HorizontalAlignment="Left" Source="{Binding ProductlmagePath, Converter={StaticResource ImagePathConverter}}"> </Image>

Рассмотренная система работает благодаря тому, что свойство Image. Source ожида­ет объект ImageSource, а класс Bitmaplmage наследует класс ImageSource. Результат показан на рис. 16.11.

Рис. 16.11. Вывод связанного изображения

Что произойдет, когда файл отсутствует? Попытка создать объект Bitmaplmage, ука­зывающий на несуществующий файл, приводит к генерации объекта исключения в момент установки свойства DataContext, ItemsSource или Source. В класс ImagePath­Converter можно добавить свойство, позволяющее устранить проблему. Например, можно добавить булево свойство SuppressExceptions. Когда оно равно True, код метода Convert () перехватывает исключение и возвращает пустую строку. Можно также до­бавить свойство Defaultlmage, содержащее заполнитель Bitmaplmage. Тогда при отсут­ствии файла будет возвращено изображение, установленное по умолчанию.

Источник: Мак-Дональд, Мэтью. Silverlight 3 с примерами на С# для профессионалов. : Пер. с англ. —- М. : ООО «И.Д. Вильяме», 2010. — 656 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии