Гибкая и мощная привязка данных в WPF

Автор: Уолт Ричер (Walt Ritscher)

Все приложения в той или иной форме зависят от данных, и большинство разработчиков пишет большой объем кода доступа к данным. Майкрософт создает инфраструктуры привязки данных в течение многих лет. Каждая из них обещает разрешить проблемы с привязкой данных навсегда. Мы продолжаем ждать, когда появится совершенная привязка данных. Может быть, привязка данных WPF — именно то, чего мы ждем?

В Windows Presentation Foundation (WPF) имеется множество сюрпризов для опытных разработчиков .NET. Необходимо изучить новую модель композиции пользовательского интерфейса, принципиально новый язык разметки XAML и сложную систему свойств зависимостей. Так много всего следует изучить, с чего же начать? Начинающим рекомендуется ознакомиться со статьей Вей-Мена Ли (Wei-Meng Lee) "An Overview of Windows Presentation Foundation" ("Обзор Windows Presentation Foundation"), опубликованной в журнале CoDe Magazine в марте-апреле 2006 г. У меня имеется собственный краткий перечень избранных концепций, которые следует изучить в WPF. Здесь я приведу две из них. Во-первых, изучите шаблоны и тесно связанные с ними стили. Они обеспечивают поразительно хороший способ проектирования и обработки пользовательского интерфейса. Во-вторых, потратьте некоторое время на изучение новой модели привязки данных. Это будет правильно потраченное время.

Инфраструктуры привязки

Привязка данных в той или иной форме присутствует повсюду в течение многих лет. Как в Windows Forms, так и в ASP.NET имеются доступные реализации привязки. Мотив создания инфраструктуры привязки состоит в том, что она уменьшает объем кода, который приходится создавать разработчику приложений. Разработчики рассчитывают, что рабочие группы в Майкрософт создадут массу кода, необходимого для упрощения ежедневных задач программирования.

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

Основная идея привязки проста. Разработчик "привязывает" некоторые элементы пользовательского интерфейса к объектам данных и полагается на инфраструктуру привязки в плане помещения данных в элементы управления и обеспечения обратного сохранения измененных данных в свойствах бизнес-объектов.

Так что же такое привязка данных WPF? Я определяю ее следующим образом: это возможность регистрации двух элементов, источника данных и целевого объекта данных, с помощью инфраструктуры привязки. Инфраструктура привязки отвечает за синхронизацию данных между этими двумя элементами и за предоставление необходимых служб, таких как проверка и преобразование данных.

Это простое объяснение вряд ли показывает всю мощь привязки WPF. WPF — это полностью новый подход к конструированию платформы разработки пользовательского интерфейса. Поскольку корпорация Майкрософт начала с чистого листа, архитекторам WPF была предоставлена возможность встраивания интересных идей в их модуль привязки. Привязка в WPF является всеобъемлющей и встроена во все части системы. Она позволяет большую степень абстракции кода и пользовательского интерфейса, разрешая полное разделение проекта пользовательского интерфейса и кода бизнес-объекта. Другой уникальной идеей в WPF являются шаблоны данных. Если предыдущий опыт работы был связан с Windows Forms или ASP.NET, то шаблоны заставят изменить представление о разработке и проектировании пользовательских интерфейсов.

Соавторы привязки данных

В модели привязки данных WPF имеется три основных участника: инфраструктура, целевой объект данных и источник данных. Настройка привязки с помощью инфраструктуры — это просто что-то вроде сообщения системе свойств зависимости WPF сведений о нужной привязке. Это делается с помощью класса расширения разметки Binding:

<TextBlock Text='{Binding Path=StreetAddress}' />

Этот короткий фрагмент XAML — все, что нужно для привязки свойства Text к свойству StreetAddress.

Целевые объекты данных

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

Целевой объект данных — это объект назначения для привязки данных. Необходимо задавать как целевой объект, так и свойство целевого объекта. Свойство целевого объекта должно быть свойством зависимостей. Свойства зависимостей являются ядром системы свойств зависимостей WPF. Они представляют инструмент реализации многих существующих в WPF функций, таких как анимация, стили, шаблоны и наследование свойств. Они также являются связующим звеном в привязке данных.

Любой тип может служить в качестве целевого объекта данных, если он предоставляет хотя бы одно "свойство зависимостей". Для поиска подходящих свойств существует простой запрос LINQ, который возвращает все свойства зависимостей в классе TextBlock.

В C#:

// using System.Windows.Controls
var q = from member
  in typeof(TextBlock).GetFields
   (BindingFlags.Public | BindingFlags.Static |
    BindingFlags.FlattenHierarchy)
  where member.FieldType ==  
    typeof(System.Windows.DependencyProperty)
  orderby member.Name
  select member.Name;

  // Examples
  // BackgroundProperty
  // CursorProperty

В Visual Basic:

' using System.Windows.Controls
  Dim q = From member In 
GetType(TextBlock).GetFields(BindingFlags.Public _
   Or BindingFlags.Static _
   Or BindingFlags.FlattenHierarchy) _
   Where member.FieldType Is _ GetType(System.Windows.DependencyProperty) _
   Order By member.Name _
   Select member.Name
  ' Examples
  ' BackgroundProperty
  ' CursorProperty

Если выполнить элемент "List of Dependency Properties" ("Список свойств зависимостей) в предоставленном демонстрационном проекте, то можно увидеть подробный список доступных свойств зависимостей для каждого элемента Framework.

Существует множество элементов WPF, которые могут служить в качестве целевых объектов данных. Некоторые из этих элементов разработаны для отображения единственного значения. В качестве примера такого типа элементов в первую очередь можно привести элементы TextBlock и Slider. ItemsControls — это элементы, отображающие списки данных. В WPF включено множество таких элементов управления, подходящих для отображения списков, в том числе ComboBox, ListBox и TreeView.

Источники данных

Один из блестящих аспектов модуля привязки данных WPF состоит в возможности привязки к почти любому источнику данных, включая данные XML, классы ADO.NET, запросы LINQ, элементы WPF и типы, реализующие IEnumerable или IList.

Как уже упоминалось выше, каждая привязка должна иметь целевой объект привязки и свойство целевого объекта. Привязка не будет завершенной, пока не будут указаны также источник данных и свойство источника.

Иногда требуется отображать одно значение из источника данных. Это может быть название шрифта в метке или дата выставления счета в элементе управления "Календарь". Возможно, потребуется привязать значение одного элемента управления к вводу другого. Я назову это привязкой "единственного свойства", поскольку официальное имя в WPF отсутствует. В WPF легко выполнить привязку единственного свойства. Далее приводится пример, показывающий, как можно привязать свойство Value элемента управления Slider к свойству FontSize элемента управления TextBlock.

<Slider x:Name='sizeSlider'
        Orientation='Vertical'
        Minimum='10'
        Maximum='80'
        Value='25' />
<TextBlock Text='Sample Text - abcde'
           Margin='5,0'
           FontSize=
'{Binding ElementName=sizeSlider, Path= Value}'/>

Источник привязки обычно представляет собой свойство объекта, поэтому в XAML привязки необходимо предоставить как объект источника данных, так и свойство источника данных. В приведенном выше примере атрибут ElementName указывает, что требуются данные из другого элемента страницы, а атрибут Path указывает соответствующее свойство. Путь привязки может представлять собой сложное значение, с углублением в иерархию элементов, но в данном случае это только имя свойства.