Привязка данных (в ее самом чистом смысле) представляет собой способность элемента управления быть подключенным к источнику данных таким образом, что данный элемент управления: отображает определенные элементы из этого источника данных и поддерживает синхронизацию с источником данных. После выполнения подключения исполняющая среда делает все необходимое для того, чтобы это работало. Реально не имеет значения, где и как хранятся данные: это может быть файловая система, коллекция объектов, объект базы данных и т. д.
Итак, кратко рассмотрим, как мы можем установить подключение привязки данных при помощи WPF. Ключевым здесь является класс System.Windows. Data.Binding. Он выступает посредником, отвечающим за связь элемента управления с источником данных. Для успешного объявления привязки нам нужно знать три вещи:
□ Какое свойство элемента управления пользовательского интерфейса мы хотим привязать?
□ К какому источнику данных мы хотим привязаться?
□ Какой конкретно элемент или свойство внутри источника данных содержит интересующие нас данные?
Мы можем привязаться либо к единичным объектам (привязка строкового свойства объекта к текстовому полю), либо к коллекциям объектов (привязка коллекции Listo к списку). В любом случае механизм остается тем же самым:
Binding binding = new Binding(); binding.Source = _stringList;
listBoxl.SetBinding(ListBox.ItemsSourceProperty, binding);
Предыдущий фрагмент кода создает объект Binding, настраивает нашу коллекцию List<string> в качестве источника объекта Binding, а затем для нашего элемента управления (ListBox) вызывает SetBinding, передавая в него экземпляр объекта Binding и то свойство элемента управления, к которому мы хотим привязать наш источник данных.
Вы можете также присвоить источники данных специальному объекту, который называется контекстом данных. Каждый объект FrameworkElement (а также и те, которые наследуют от этого класса) реализует собственный экземпляр DataContext. Вы можете представлять его себе как некую глобальную область, куда элементы управления могут обращаться за получением своих данных (при участии в цепочке привязки данных).
Это значительно упрощает наш код привязки данных. Мы можем настроить контекст в конструкторе Window следующим образом:
this.DataContext = _stringList;
Теперь мы просто указываем этот контекст данных при помощи тега в XAML-элементе для ListBox:
CListBox Name="listBoxl" IternsSource="{Binding}" />
Привязывающий объект в этом случае будет автоматически искать объекты, скрытые в контексте данных где-то внутри дерева объектов. Когда он найдет такой объект, он автоматически привяжет его.
Это хорошо работает для нашего простого примера List<string>, но что если мы попытаемся привязать к списку целую коллекцию нестандартных объектов? Если у нас есть простой класс Employee со свойствами Name и PhoneNbr, то как нам привязать коллекцию этих объектов и показать имя сотрудника? Процесс останется таким же. Если мы создаем класс Employee, а затем создаем коллекцию List<Employee>, то весь этот код по-прежнему работает. Но есть и проблема. Она показана на рис. 16.18.
Рис. 16.18. Привязка к нестандартным объектам
Мы еще не сказали движку привязки, как именно мы хотим представить наши данные в списке. По умолчанию процесс привязки просто вызовет Tostring для каждого объекта.
Быстрым решением этой проблемы было бы просто перекрыть метод Tostring: public override string ToString()
{
return _name;
}
В данном случае это решит проблему. Но более надежный подход потребует использования DataTemplate. Мы опишем этот подход в разд. "Создание простого приложения для просмотра изображений" далее в этой главе.