Главная » Разработка для Windows Phone 7 » Конвертеры со свойствами Windows Phone 7

0

Нет ничего безрассудного в создании конвертера привязки данных, настолько специализированного или причудливого, что он будет иметь очень узкое применение. Например, рассмотрим класс DecimalBitToBrushConverter (Конвертер десятичного разряда в кисть). Этот конветер включает два открытых свойства: ZeroBitBrush (Кисть нулевого двоичного разряда) и OneBitBrush (Кисть единичного двоичного разряда).

Проект Silverlight: BinaryClock Файл: DecimalBitToBrushConverter.cs

using          System;

using          System.Globalization;

using          System.Windows.Data;

using          System.Windows.Media;

namespace BinaryClock {

public class DecimalBitToBrushConverter : IValueConverter {

public Brush ZeroBitBrush { set; get; } public Brush OneBitBrush { set; get; }

public object Convert(object value, Type targetType,

object parameter, CultureInfo culture)

{

int number = (int)value;

int bit = Int32.Parse(parameter as string); int digit = number / PowerOfTen(bit / 4) % 10;

return ((digit & (1 << (bit % 4))) == 0) ? ZeroBitBrush : OneBitBrush;

}

public object ConvertBack(object value, Type targetType,

object parameter, CultureInfo culture)

{

return null;

}

int PowerOfTen(int exp) {

int value = 1;

for (int i = 0; i < exp; i++) value *= 10;

return value;

}

}

}

Метод Convert ожидает аргумент value типа int и действительный аргумент parameter. Если свойству ConverterParameter в XAML задано строковое значение, оно будет передано в метод Convert как объект типа string. Вот здесь потребуется преобразовать его в требуемый тип вручную. (Чтобы переопределить это поведение, необходимо использовать для ConverterParameter синтаксис свойство-элемент и задавать тип с помощью тегов элемента.) Данный метод Convert ожидает, что передаваемая в него строка представляет другой тип int, поэтому передает ее в метод Int32.Parse.

Аргумент value имеет числовое значение, например, 127. Аргумент parameter, преобразованный в int, представляет двоичный разряд, например, 6. По сути метод разбивает передаваемое в него число на десятичные разряды (в данном примере это 1, 2 и

7) и затем выбирает разряд, соответствующий заданному двоичному разряду. 7 в числе 127 соответствует двоичным разрядам от 0 до 3; 2 в числе 127 соответствует двоичным разрядам от 4 до 7; 1 в числе 127 соответствует двоичным разрядам от 8 до 11.

Если в данном двоичном разряде хранится 1, Convert возвращает OneBitBrush; если 0, Convert возвращает ZeroBitBrush.

Я использую этот конвертер в проекте BinaryClock (Двоичные часы). На него ссылается производный от UserControl класс BinaryNumberRow (Строка двоичного числа). Обратите внимание, два открытых свойства DecimalBitToBrushConverter задаются прямо в коллекции Resources, которая также включает Style для Ellipse.

Проект Silverlight: BinaryClock Файл: BinaryNumberRow.xaml

<UserControl

x:Class="BinaryClock.BinaryNumberRow"

xmlns="http://schemas.microsoft.com/winfx/2 0 0 6/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2 0 0 6/xaml" xmlns:petzold="clr- namespace:Petzold.Phone.Silverlight;assembly=Petzold.Phone.Silverlight" xmlns:local="clr-namespace:BinaryClock">

<UserControl.Resources>

<Style x:Key="ellipseStyle" TargetType="Ellipse"> <Setter Property="Width" Value="48" /> <Setter Property="Height" Value="48" />

<Setter Property="Stroke" Value="{StaticResource PhoneForegroundBrush}"

/>

<Setter Property="StrokeThickness" Value="2" /> </Style>

<local:DecimalBitToBrushConverter x:Key="converter"

ZeroBitBrush="{x:Null}" 0neBitBrush="Red" />

</UserControl.Resources>

<petzold:UniformStack 0rientation="Horizontal">

<Ellipse Style="{StaticResource ellipseStyle}"

Fill="{Binding Converter={StaticResource converter}, ConverterParameter=6}" />

<Ellipse Style="{StaticResource ellipseStyle}"

Fill="{Binding Converter={StaticResource converter}, ConverterParameter=5}" />

<Ellipse Style="{StaticResource ellipseStyle}"

Fill="{Binding Converter={StaticResource converter}, ConverterParameter=4}" />

<Ellipse Style="{StaticResource ellipseStyle}" Stroke="{x:Null}" />

<Ellipse Style="{StaticResource ellipseStyle}"

Fill="{Binding Converter={StaticResource converter}, ConverterParameter=3}" />

<Ellipse Style="{StaticResource ellipseStyle}"

Fill="{Binding Converter={StaticResource converter}, ConverterParameter=2}" />

<Ellipse Style="{StaticResource ellipseStyle}"

Fill="{Binding Converter={StaticResource converter}, ConverterParameter=1}" />

<Ellipse Style="{StaticResource ellipseStyle}"

Fill="{Binding Converter={StaticResource converter}, ConverterParameter=0}" />

</petzold:UniformStack> </UserControl>

Тело дерева визуальных элементов BinaryNumberRow образует горизонтально ориентированный UniformStack, содержащий семь элементов Ellipse. У каждого из них есть Binding, задающий в качестве значения свойства Converter класс DecimalBitToBrushConverter, и ConverterParameter, значения которого меняются от 0 для крайнего справа Ellipse до 6 для крайнего слева Ellipse. Ни одна из привязок не включает параметров Source или Path! Очевидно, что они задаются где-то в другом месте в DataContext для экземпляра BinaryNumberRow.

В файле MainPage.xaml проекта BinaryClock экземпляр объекта TwelveHourClock создается в разделе Resources:

Проект Silverlight: BinaryClock Файл: MainPage.xaml

<phone:PhoneApplicationPage.Resources>

<petzold:TwelveHourClock x:Key="clock12" /> </phone:PhoneApplicationPage.Resources>

Область содержимого включает центрированный по вертикали StackPanel с тремя экземплярами BinaryNumberRow:

Проект Silverlight: BinaryClock Файл: MainPage.xaml

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

<StackPanel DataContext="{StaticResource clock12}" VerticalAlignment="Center">

<local:BinaryNumberRow DataContext="{Binding Hour12}"

Margin="0 12" />

<local:BinaryNumberRow DataContext="{Binding Minute}"

Margin="0 12" />

<local:BinaryNumberRow DataContext="{Binding Second}"

Margin="0 12" />

</StackPanel> </Grid>

Обратите внимание на параметры DataContext. В качестве значения свойства DataContext объекта StackPanel задан сам TwelveHourClock. DataContext каждого элемента управления задано одно из свойств TwelveHourClock. Вот поэтому в описаниях Binding класса BinaryNumberRow должны присутствовать только Converter и ConverterParameter.

В результате получаем, конечно же, двоичные часы:

И время, хммм, 12:58:06.

А можно ли еще больше сократить разметку Binding? Предположим, для всех элементов Ellipse задан один и тот же Converter. Можно ли и этот параметр перенести в описание DataContext для StackPanel? Нет, нельзя. Параметры Converter и ConverterParameter должны располагаться вместе в одном описании Binding.

Источник: Чарльз Петзольд, Программируем Windows Phone 7, Microsoft Press, © 2011.

По теме:

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