Гибкая и мощная привязка данных в WPF (продолжение)
Автор: Уолт Ричер (Walt Ritscher) Уведомление об изменении Почти любое свойство .NET может служить в качестве источника данных. В предыдущем примере источником данных было свойство Value элемента Slider, которое возвращает значение типа Double. Данные загружаются в целевой объект данных при инициализации. Если устанавливается двусторонняя привязка (подробности ниже в этой статье), то данные будут возвращаться назад в источник данных. Система зависимостей WPF может также сохранять обратную синхронизацию данных в целевом объекте данных в случае, когда изменяется свойство источника. Однако этот процесс не автоматический. Чтобы это выполнялось, свойство источника должно реализовывать некоторую форму уведомления об изменении. Выбранный тип должен сообщать инфраструктуре, что базовые данные изменены. Существует несколько способов осуществить это в источнике данных.
Пример бизнес-объекта, реализующего INotifyPropertyChanged, см. в листинге 1, а пример подхода с использованием DependencyProperty см. в листинге 2. Контекст данных Конечно, в WPF нет ограничений на применение элементов пользовательского интерфейса в качестве источников данных. WPF также предоставляет возможность привязки данных, не относящихся к пользовательскому интерфейсу. Для каждой привязки необходим объект источника данных и путь к свойству источника. Контекст данных позволяет инфраструктуре искать исходный объект далее по логическому дереву. Все элементы FrameworkElements и FrameworkContentElements имеют свойство DataContext. Например: <TextBlock Text='{Binding Path=Salary}' /> Что же здесь происходит? Свойство Path указывает на свойство Salary, но где XAML, задающий источник данных? Чтобы ответить на этот вопрос, рассмотрим следующий код. В C#:
В Visual Basic:
Контекст данных устанавливается в коде. В последней строке этого фрагмента устанавливается контекст данных для всей страницы. Если объект привязки не обнаруживает контекст данных в TextBlock, он проходит по логическому дереву, ища контекст данных в родительском элементе. Если контекст данных не обнаруживается и там, то выполняется обработка ошибок по умолчанию. В следующем фрагменте кода показано, как можно применять разные контексты данных к элементам на странице. В C#:
В Visual Basic:
Класс Binding имеет конструктор, принимающий строку Path. Это означает, что можно полностью исключить свойство Path полностью и использовать короткий синтаксис, как показано ниже.
Расширение привязки Класс Binding — это основной действующий персонаж в истории привязки данных. Он имеет простой и понятный API. Далее приводятся некоторые наиболее часто используемые свойства привязки.
Что может быть источником данных В качестве источника данных можно использовать любой тип, если он имеет общий конструктор без параметров и хотя бы одно общее свойство. Ниже приводится пример привязки к System.String. В этом примере оба элемента TextBlock имеют имя, что делает их доступными в CS-файле и в VB-файле. Привязка textBox2 устанавливается в файле XAML, а контекст данных — в коде программной части.
В файле кода программной части C#:
В файле кода программной части Visual Basic:
Хранение элементов в ресурсах Я собираюсь за несколько минут показать, как устанавливать привязку без написания какого-либо кода. Да, я говорю только о привязке XAML. Однако, прежде чем приступить к этому предмету, я хочу потратить несколько минут на обсуждение ресурсов XAML. Инфраструктура ресурсов существует для предоставления многократно используемых элементов в XAML. Я начну с рассмотрения средства синтаксического анализа XAML. Когда средство синтаксического анализа XAML обнаруживает элемент WPF в файле XAML, оно создает экземпляр базового типа. Это возможно, поскольку.в пространстве имен https://schemas.microsoft.com/winfx/2006/xaml/presentation имеется однозначное (один-к-одному) сопоставление между всеми его элементами, и в сборке .NET существует класс WPF. Таким образом, средство синтаксического анализа знает, как включить элемент <Button> в экземпляр класса System.Windows.Controls.Button. При использовании редактора XAML Visual Studio для написания XAML это в значительной степени скрыто. IntelliSense показывает разрешенные элементы, и компилятор помечает все элементы, которые он не может распознать. При написании кода часто создаются переменные для хранения экземпляров классов, чтобы можно было ссылаться на них в любом месте кода. Архитекторы WPF считали, что в XAML также важно реализовать многократно используемые элементы. Так родилась инфраструктура ресурсов. Чтобы создать переменную XAML, ее следует добавить в ResourceDictionary. Для ссылки на хранимый элемент используется расширение разметки StaticResource или DynamicResource. Теперь необходимо только узнать, как создать словарь ресурсов в XAML. Краткое изучение API WPF показывает, что каждый FrameworkElement имеет словарь ресурсов, доступный в его свойстве Resources. Возьмите любой элемент инфраструктуры в файле XAML, добавьте элемент в его свойство Resources, и этот элемент будет доступен в данном элементе инфраструктуры и во всех его дочерних объектах. Поскольку ResourceDictionary хранит все элементы в простой хэш-таблице, все, что требуется для добавления элемента, это ключ и экземпляр объекта. Прежде чем показать способ XAML, я покажу эквивалент, написанный в коде. Следующий пример показывает, как добавить стиль в несколько текстовых полей в файле кода программной части. В C#:
В Visual Basic:
В этом примере сначала создается переменная стиля, а затем добавляется несколько методов задания свойств. После добавления методов задания стиля в коллекцию Setters стиль применяется к отдельным текстовым полям. Чтобы выполнить то же в XAML, необходимо создать элемент (переменную) в разделе Resources. Затем с помощью расширения разметки StaticResource следует назначить этот ресурс текстовым полям. В XAML:
Стили — не единственный элемент, который можно хранить в словаре ресурсов. Обычно в словаре ресурсов также сохраняются кисти и шаблоны. Фактически, как можно будет видеть в следующем разделе, можно создавать и хранить в словаре ресурсов почти любой тип .NET. На данный момент показано, как выполнять привязку в коде. В следующем выпуске CoDe Magazine я буду рассматривать привязку XAML. |