Главная » WPF » Отображение, управляемое данными

0

В большинстве приложений автор конструирует простой пользовательский ин

терфейс, создает модель данных, а затем объединяет то и другое с помощью связы

вания.  Но WPF позволяет  и обратить  это привычное  отношение:  данные можно сделать первичными, а интерфейс вторичным. В результате удается построить раз витую визуализацию данных, независимую  от способа использования. Ключом к этой модели служат три класса: ContentControl, ItemsControl и DataTemplate.

Начнем с простой модели данных – изображения. В главе 5 мы видели, что для работы  с изображениями есть два основных  типа  данных:  элемент  управления Image и иерархия  классов, производных от ImageSource (в том числе и наиболее употребительный класс BitmapImage). В пользовательских интерфейсах элемент Image применяется чаще всего. И самый простой способ его применения – запи сать URI изображения в свойство Source:

<Image Source=’c:\data\book\images\flowers.jpg’ />

Свойство  Source на самом деле определено в классе ImageSource,  и мы можем задать в качестве его значения прямо BitmapImage, если хотим управлять деталя ми загрузки  (например, декодировать  разрешающую  способность):

<Image>

<Image.Source>

<BitmapImage UriSource=’c:\data\book\images\flowers.jpg’ />

</Image.Source>

</Image>

А теперь обратим эту модель: вместо того чтобы использовать элемент Image и запол нять его данными, начнем с самих данных (изображения) и посмотрим, как их отобра зить. Поскольку изображение только одно, воспользуемся элементом ContentControl:

<ContentControl>

<ContentControl.Content>

<BitmapImage UriSource=’c:\data\book\images\flowers.jpg’ />

</ContentControl.Content>

</ContentControl>

Эта программа выводит строку, как показано на рис. 6.21, – не слишком интересно.

Рис. 6.21. Вывод растрового изображения с помощью ContentControl

Здесь элемент ContentControl видит данные, в данном случае растровое изоб

ражение, и вызывает метод ToString для формирования визуального отображе

ния. После добавления  шаблона данных картинка  перестает быть такой скучной. Сначала  определим простой шаблон, в котором для вывода изображения приме няется элемент Image (рис. 6.22):

<DataTemplate DataType=’{x:Type BitmapImage}’>

<Image Source=’{Binding}’ />

</DataTemplate>

Рис. 6.22. Вывод растрового изображения по более интересному шаблону

Как видно из рис. 6.22, отображение  стало куда интереснее.  Но по существу оно ничем не отличается  от того, что мы имели с самого начала при использова нии элемента Image. Добавим немного разнообразия (рис. 6.23):

<DataTemplate DataType=’{x:Type BitmapImage}’>

<Border>

<Border HorizontalAlignment=’Center’ VerticalAlignment=’Center’ Margin=’4’ BorderThickness=’1’ BorderBrush=’Black’ Padding=’4’ Background=’White’>

<Border.BitmapEffect>

<DropShadowBitmapEffect Softness=’.2’ ShadowDepth=’1’/>

</Border.BitmapEffect>

<Image Source=’{Binding}’ />

</Border>

</Border>

</DataTemplate>

Рис. 6.23. Вывод растрового изображения с дополнительными элементами

Можно  было бы пойти еще дальше, добавив средства для сдвига картинки и другие полезные  вещи (рис. 6.24).

Важно отметить, что модель данных, описывающая изображение,  не измени лась. Представьте на секунду,  что вместо  BitmapImage мы взяли  бы в качестве данных объект Customer.  Можно  было бы создать модель данных клиента,  опи сав свойства, поведение и т.д., а затем сконструировать различные пользовательс кие интерфейсы для взаимодействия с этими данными.

Конструировать интерфейс,  исходя из данных, хорошо тем, что получающееся представление можно повторно  использовать в любом месте приложения. Техника программирования, которую можно условно  назвать  «сначала  данные», применима на многих уровнях. Пусть, например, нам нужно вывести список изображений. Пона чалу возникает  искушение воспользоваться списковым полем и зашить список изоб ражений в код. В том месте, где список понадобился в первый раз, это неплохо и срав нительно просто, но, если его нужно отображать в нескольких  местах, то хотелось бы повторно использовать определение способа отображения списка. Возможно, это бу дет обычное списковое поле с горизонтальной или вертикальной прокруткой, а, быть может, элемент  ListView  с несколькими колонками,  в которых выводятся дополни тельные данные. Если мы начнем с определения нового типа для списка изображений, то сможем создать для него шаблон точно так же, как для одного изображения:

using System.Collections.ObjectModel;

public class ImageList : ObservableCollection<BitmapImage> {}

Рис. 6.24. Более сложные дополнительные элементы, в том числе действия и еще одно связывание

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

<Window …>

<l:ImageList>

<BitmapImage … />

<BitmapImage … />

<BitmapImage … />

</l:ImageList>

</Window>

Рис. 6.25. Повторное использование сложного шаблона в списке

Чтобы описать, как этот список должен выглядеть  (рис. 6.25), мы проделаем то же самое, что для одного изображения:

<DataTemplate DataType=’{x:Type l:ImageList}’>

<ListBox ItemsSource=’{Binding}’ />

</DataTemplate>

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

Чего мы достигли?

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

Источник: К. Андерсон  Основы  Windows Presentation Foundation. Пер. с англ. А. Слинкина — М.: ДМК Пресс, 2008 — 432 с.: ил.

По теме:

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