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

0

Данная глава посвящена созданию пользовательских классов элементов управления в Silverlight. В ней рассказывается, как сделать их доступными через библиотеки динамической компоновки, и как работать с ними в коде и разметке.

Наследование одного класса от другого является настолько базовым аспектом объектно- ориентированного программирования, что в том, чтобы посвящать ему целую главу, кажется, нет необходимости. С одной стороны, в наследовании пользовательских классов от существующих классов Silverlight нет ничего особенного. Полученный класс можно использовать в XAML, просто объявив пространство имен XML, чтобы связать префикс XML с пространством имен .NET. Именно это было продемонстрировано мною в главе 9 в двух проектах, представлявших примеры создания пользовательских панелей.

С другой стороны, если создается класс пользовательского элемента управления, и этот класс определяет новые свойства, и если требуется задавать значения этих свойств через стили или привязки данных, или требуется назначить их целью анимации, с этими свойствами требуется сделать нечто очень особенное.

Их необходимо сделать свойствами-зависимостями.

Описание проблемы

Для иллюстрации разницы, обеспечиваемой свойствами-зависимостями, рассмотрим сначала класс пользовательского элемента управления, написанный начинающим разработчиком.

Предположим, требуется создать приложение с множеством кнопок, закрашенных с применением различных градиентных кистей. Мы решаем, что удобней будет задать два цвета как свойства кнопок. Назовем свойства Color1 и Color2. Итак, открываем проект NaiveGradientButtonDemo (Демонстрация простой кнопки с градиентом) и добавляем новый класс под именем NaiveGradientButton (Простая кнопка с градиентом). Вот этот класс:

Проект Silverlight: NaiveGradientButtonDemo Файл: NaiveGradientButton.cs (фрагмент)

public class NaiveGradientButton : Button {

GradientStop gradientStop1, gradientStop2;

public NaiveGradientButton() {

LinearGradientBrush brush = new LinearGradientBrush(); brush.StartPoint = new Point(0, 0); brush.EndPoint = new Point(1, 0);

gradientStop1 = new GradientStop(); gradientStop1.Offset = 0; brush.GradientStops.Add(gradientStop1);

gradientStop2 = new GradientStop(); gradientStop2.Offset = 1; brush.GradientStops.Add(gradientStop2);

Foreground = brush;

public Color Color1 {

set { gradientStop1.Color = value; }

get { return (Color)gradientStop1.Color; }

}

public Color Color2 {

set { gradientStop2.Color = value; }

get { return (Color)gradientStop2.Color; }

}

}

Как и ожидалось, NaiveGradientButton наследуется от Button и включает два новых свойства типа Color: Color1 и Color2. Конструктор создает LinearGradientBrush, задает значения свойств StartPoint и EndPoint, создает два объекта GradientStop, хранящихся как поля, добавляет их в LinearGradientBrush и затем определяет эту кисть как значение свойства Foreground кнопки.

Этот класс не препятствует повторному заданию свойства Foreground объекта GradientBrush в коде или XAML после создания объекта, но поскольку заданное здесь значение Foreground является локальным параметром, свойство Foreground не будет наследоваться, и на него не будет распространяться действие Style, целевым свойством которого является Foreground.

Как видите, методы доступа для получения и задания значений свойств Color1 и Color2 просто выполняют доступ к свойству Color в соответствующем GradientStop.

Этот класс используется в файле MainPage.xaml проекта NaiveGradientButtonDemo. Корневой элемент включает описание пространства имен XML, которое связывает префикс пространства имен «local» с пространством имен CLR NaiveGradientButton:

xmlns:local="clr-namespace:NaiveGradientButtonDemo"

Коллекция Resources в MainPage.xaml определяет Style для NaiveGradientButton: Проект Silverlight: NaiveGradientButtonDemo Файл: MainPage.xaml (фрагмент)

<phone:PhoneApplicationPage.Resources> <Style x:Key="gradientButtonStyle"

TargetType="local:NaiveGradientButton"> <Setter Property="HorizontalAlignment" Value="Center" />

<! -<Setter Property="Color1" Value="Cyan" />

<Setter Property="Color2" Value="Pink" /> — >

</Style>

</phone:PhoneApplicationPage.Resources>

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

Также нетрудно заметить, что я закомментировал теги Setter, где задаются значения свойствам Color1 и Color2. (Наверное, я не так наивен, как иногда притворяюсь.)

В области содержимого, описываемой XAML-файлом, располагается четыре экземпляра NaiveGradientButton, значения свойств Color1 и Color2 которых заданы самыми различными способами:

Проект Silverlight: NaiveGradientButtonDemo Файл: MainPage.xaml (фрагмент)

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

<local:NaiveGradientButton Content="Naive Gradient Button #1"

HorizontalAlignment="Center" />

<local:NaiveGradientButton Content="Naive Gradient Button #2"

Color1="Blue" Color2="Red" HorizontalAlignment="Center" />

<local:NaiveGradientButton Content="Naive Gradient Button #3"

Color1="{StaticResource PhoneForegroundColor}" Color2="{StaticResource PhoneBackgroundColor}" HorizontalAlignment="Center" />

<local:NaiveGradientButton Content="Naive Gradient Button #4"

Style="{StaticResource gradientButtonStyle}" />

</StackPanel> </Grid>

Первая кнопка использует для Color1 и Color2 значения по умолчанию; для второй цвета задаются явно; третья ссылается на цвета темы; и четвертая использует Style, описанный в коллекции Resources.

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

Color1 и Color2 не имеют значений по умолчанию. Если они не заданы явно, для цветов в градиенте все свойства A, R, G и B будут равны 0, а это соответствует прозрачному черному.

Раскомментируем два тега Setter в Style. Окно ошибок Visual Studio сообщит о том, что «Object reference not set to an instance of an object[13]» (несомненно, мое самое любимое сообщение об ошибке). Если попытаться запустить приложение в отладчике, будет сформировано исключение XamlParseException (Исключение синтаксического анализатораXAML) и выведено сообщение: «Invalid attribute value Colorl for property Property[14]». Вот это немного лучше и говорит о том, что свойству Property тега не может быть присвоено значение Color1.

Но лучше бы сообщения об ошибках говорили: «Не будь таким наивным! Используй свойства-зависимости.»

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

По теме:

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