Реализация шаблонов Master/Detail в Silverlight 2

Основной целью дизайна в Silverlight и WPF является предоставляемая разработчикам возможность с легкостью инкапсулировать функциональность пользовательского интерфейса в элементы управления, который можно повторно использовать. Разработчики могут реализовать новые специализированные элементы управления унаследовав класс из одного из существующих классов Control (либо класс, основанный на Control, из такого элемента управления, как TextBox, Button и т.д.). В качестве альтернативы можно создать пользовательские элементы управления (User Control) для повторного использования, которые можно с легкостью создать при помощи разметки XAML, и которые также легко реализовать.

Для нашего приложения Digg необходимо реализовать шаблоны Master/Detail, где приложение позволяет пользователю осуществлять поиск по тематике, заполнять список статьями по данной тематике и затем позволит пользователю выбрать ту статью, о которой впоследствии будет показана краткая информация. К примеру, выбрав статью в следующем списке:


мы получим следующий результат:

Мы реализуем данное поведение путем создания пользовательского элемента управления "StoryDetailsView" , который мы отобразим на экране после того, как будет выбрана статья в нашем ListBox.

Создание пользовательского элемента управления StoryDetailsView

Мы начнем с правого клика по узлу Visual Studio в нашем проекте DiggSample и выберем опцию добавления нового элемента "Add New Item". Это откроет диалоговое окно нового элемента. Мы выберем шаблон элемента UserControl (пользовательского элемента) и назовем новый элемент управления "StoryDetailsView":

Это добавит новый элемент UserControl с данным именем в наш проект DiggSample:


Создание стандартного диалогового окна

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

Существует несколько способов реализации этого. Для данного случая мы начнем действия с открытия пользовательского элемента управления StoryDetailsView.xaml и добавления XAML-содержимого к нему:


Первый элемент <Rectangle> настраивается таким образом, чтобы он занимал все пространство окна. Его фон будет серым и полупрозрачным (поскольку его свойство прозрачности (Opacity) будет равно .765, тем самым у вас будет возможность видеть то, что находится под ним). Второй элемент <Border> затем будет помещен поверх элемента Rectangle, и он будет иметь фиксированную ширину, синий фон, а также содержать кнопку закрытия (Close).

Вот что будет отображено на экране элементом управления StoryDetailsView в данном случае:


Мы можем реализовать метод "CloseBtn_Click" обработчика события в классе фонового кода пользовательского элемента управления. После передачи, обработчик события кнопки закрытия установит свойство Visibility элемента UserControl в "Collapsed" , что заставит исчезнуть окошко с экрана и возвратит пользователя к содержимому основной страницы:


Отображение элемента управления StoryDetailsView

Легким способом отображения пользовательского элемента управления StoryDetailsView на экране будет добавление его в конец файла Page.xaml и установка его свойства видимости в значение Collapsed (то есть его не будет видно при первом запуске приложения):


Затем мы можем обработать событие "SelectionChanged" из нашего элемента управления ListBox в пределах класса с фоновым кодом файла Page.xaml:


Когда пользователь выбирает определенную статью в списке, мы можем использовать обработчик события SelectionChanged элемента ListBox для того, чтобы установить свойство Visibility нашего элемента управления ShowDetailsView в "Visible" :


Это вызовет отображение диалогового окна на экране. Когда пользователь нажимает кнопку закрытия окна ("Close"), оно исчезает и пользователь заново может выбрать статью и повторить процесс.

Передача информации в элемент управления StoryDetailsView

Наконец, в элементе StoryDetailsView нам необходимо отобразить детальную информацию о статье, выбранной пользователем из списка ListBox. 

В пределах нашего обработчика события "SelectionChanged" элемента ListBox (который находится в пределах класса с фоновым кодом страницы), мы можем получить доступ к объекту с данными DiggStory, который соответствует выбранной строке в ListBox путем получения доступа к свойству "SelectedItem" элемента ListBox. 

Один из способов, который мы можем использовать для передачи данного объекта DiggStory в пользовательский элемент управления StoryDetailsView, является установка свойства "DataContext" в выбранный объект DiggStory как раз перед тем, как отображать пользовательский элемент управления:

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

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


И когда пользователь нажимает на статью в списке:


наш обработчик события ListBox обработает выделение, установит DataContext пользовательского элемента в объект DiggStory выбранной статьи и затем сделает пользовательский элемент управления видимым:


Обратите внимание как заголовок DiggStory появляется в пользовательском элементе управления из-за добавленного выражения привязки.

Завершение редактирования внешнего вида нашего элемента управления

Наш пример демонстрирует основы шаблонов Master/Detail. Мы можем завершить отображение StoryDetailsView добавлением других элементов управления и выражений привязки данных к пользовательскому элементу управления. 


Мы можем обновить пользовательский элемент управления StoryDetailsView таким образом, что он будет выглядеть как тот, что продемонстрирован выше, путем обновления его элемента управления <Border> следующим образом:


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

Следующие шаги

Теперь мы реализовали всю основную функциональность и принцип взаимодействия для нашего приложения Digg.com.

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

Источник