Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
course_(Windows&Web).docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
4.68 Mб
Скачать

Директивы препроцессора

Когда между Silverlight и WPF версиями кода достаточно мало отличий, можно воспользоваться директивами препроцессора, чтобы включить тот или иной блок кода в зависимости от того, в каком проекте компилируется данный файл. Для удобства шаблон проекта Silverlight определяет константу “SILVERLIGHT”. Конечно, возможно определить самостоятельно что-то более короткое и менее сложное в написании, однако надежнее оставить всё как есть – неизвестно, когда и где придется повторно использовать этот код.

Выглядеть это будет следующим образом:

1: private TextBox _dataTextBox;

2: public override void OnApplyTemplate()

3: {

4: #if SILVERLIGHT

5: _dataTextBox = this.GetTemplateChild("PART_DataTextBox")

6: as TextBox;

7: #else

8: _dataTextBox = this.Template.FindName("PART_DataTextBox",

9: this) as TextBox;

10: #endif

11: }

Разделяемые классы

В то время как директивы препроцессора подходят для небольших отличий в коде, по мере увеличения таких блоков код становится достаточно трудночитаем. В таких случаях более подходящими являются разделяемые классы: общий код определяется в части, которая при помощи ссылки разделяется между обоими проектами; методы, реализация которые различна, помещаются в другую часть, специфичную для каждого проекта.

Простейшее приложение, созданное в соответствии с данными принципами, выглядит следующим образом:

Рисунок 10.6. Простейшее WPF/Silverlight приложение с разделяемыми классами

MyControlWPF – это WPF проект. Он содержит файл MyControl.cs, в котором определен разделяемый класс MyControl. Этот файл состоит из кода, который идентичен и в WPF, и в Silverlight. Он добавлен в MyControlSL (Silverlight проект) в качестве ссылки. Таким образом, достаточно поддерживать одну копию файла, который используется в обоих проектах. MyControl.WPF.cs и MyControl.SL.cs в свою очередь содержат члены класса MyControl, реализация которых различна в WPF и Silverlight.

Синхронное использование xaml

К сожалению, в случае XAML не существует встроенной поддержки директив препроцессора или схожего приема разделения отличных блоков кода. Конечно, существуют некоторые сторонние решения, однако хоть это и выглядит прогрессивно с точки зрения энтузиаста, кроме случаев действительно больших XAML файлов, сложных в поддержке, обычно более разумно работать с 2 файлами, если различия в разметке не удается обойти. Таким образом, следует либо составлять такую XAML разметку, которая будет корректна как в Silverlight, так и в WPF, и создать ссылку на этот файл в одном из проектов, либо поддерживать 2 параллельные версии файла.

Решение проблем недостающего функционала Отсутствие FrameworkPropertyMetadata

Как известно, в Silverlight отсутствует класс FrameworkPropertyMetadata. Одна из наиболее часто используемых возможностей этого FrameworkPropertyMetadata по сравнению с имеющемся в Silverlight PropertyMetadata – это логические переключатели, которые управляют влиянием свойства на различные аспекты прорисовки объекта, такие как AffectsMeasure, AffectsArrange, и другие. Если один из флагов установлен в истинное значение, соответствующий аспект объявляется недействительным.

К счастью, данное поведение достаточно легко эмулировать при помощи PropertyMetadata и PropertyChangedCallback. Так, если в случае разработки только для WPF можно написать:

1: public static readonly DependencyProperty SomethingProperty

2: = DependencyProperty.Register(

3: "Something", typeof(string), typeof(Window1),

4: new FrameworkPropertyMetadata(string.Empty,

5: FrameworkPropertyMetadataOptions.AffectsMeasure)

6: );

То универсальный WPF/Silverlight код, достигающий такого же эффекта, будет выглядеть следующим образом:

1: public static readonly DependencyProperty SomethingProperty

2: = DependencyProperty.Register(

3: "Something", typeof(string), typeof(Window1),

4: new PropertyMetadata(string.Empty,

5: new PropertyChangedCallback(

6: Window1.SomethingProperty_Changed)));

7: 

8: private static void SomethingProperty_Changed(

9: DependencyObject d, DependencyPropertyChangedEventArgs e)

10: {

11: ((FrameworkElement)d).InvalidateMeasure();

12: }

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]