Улучшение пользовательского интерфейса
Разработанное Silverlight-приложение является работоспособным и может использоваться для обработки информации о сотрудниках предприятия. Однако вопросы эффективности интерфейса или взаимодействия с пользователем ( User Experience, UX ) можно улучшить. При разработке пользовательских интерфейсов UX означает общую концепцию их удобства при использовании программного обеспечения, логичность и простоту в расположении элементов управления [[5]].
Для улучшения UX пользовательского интерфейса разработанного Silverlight-приложения поставим следующие задачи:
улучшить представление элементов списка listBoxEmployees в различных состояниях (не выбранный элемент, выбранный элемент, элемент, на который наведен указатель мыши);
улучшить представление кнопок в различных состояниях (доступная, недоступная, наведен указатель мыши).
Изменение визуального поведения элемента ListBox
Для элементов пользовательского интерфейса объект ControlTemplate задает визуальную структуру и визуальное поведение элемента управления. Можно настраивать внешний вид элемента управления, предоставляя ему новый шаблон ControlTemplate без изменения его функциональности.
Для нашего приложения ставится задача создания следующего визуального представления и поведения элемента управления ListBox – listBoxEmployees:
список не должен иметь внешней рамки;
элементы списка должны представляться в двойной рамке со скругленными углами;
выбранный элемент списка должен иметь жирное выделение для внешней рамки, например светло-голубым цветом;
элемент списка, на который наведен указатель мыши, должен иметь жирное выделение для внешней рамки, например светло-фиолетовым цветом
полоса прокрутки должна находиться справа и отдельно от элементов списка.
Перед изменением представления интерфейсного элемента ListBox целесообразно подготовить объектные ресурсы для задания цветов и кистей рисования. Ресурсы цветов и кистей организуем с помощью словаря ресурсов в файле ColorsAndBrushesRD.xaml (XAML-описание приведено в приложении).
Для реализации требуемого визуального представления и поведения элемента управления ListBox спроектируем три стиля:
стиль, используемый при визуализации контейнеров элементов ListBox – ListBoxItemStyle;
стиль, используемый для элемента контроля ListBox - ListBoxPhotoStyle ;
стиль, используемый для прокручиваемой области, в которой могут содержаться другие видимые элементы – ScrollViewerPhotoStyle.
Кроме того, необходимо выделить в отдельный ресурс шаблон используемый для формирования данных отдельного элемента списка ListBox – ListBoxItemPhotoDataTemplate.
Стиль ListBoxItemStyle создается для типа ListBoxItem (TargetType="ListBoxItem") и в нем определяются четыре свойства: Padding, VerticalAlignment, HorizontalAlignment и Template.
Style x:Key="ListBoxItemStyle" TargetType="ListBoxItem">
<Setter Property="Padding" Value="1"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Template">
<Setter.Value>
. . .
<!—Определение вложенного свойства ControlTemplate -->
. . .
</Setter.Value>
</Setter>
</Style>
Основная задача при формировании визуального представления и поведения элемента управления ListBoxItem сводится к заданию вложенного свойства ControlTemplate. Это определяется тем, что визуальная структура и визуальное поведение интерфейсного элемента задается в его шаблоне ControlTemplate.
<ControlTemplate TargetType="ListBoxItem">
<Border
Name="Border"
Padding="5"
Width="200" Height="126"
CornerRadius="5"
Background="{StaticResource ListBoxItemPhotoActiveBGSolidBrush}">
<!—Определение визуального поведения в различных состояниях -->. . .
<Border
BorderBrush="{StaticResource PhotoSelectedBGSolidBrush}"
BorderThickness="1"
CornerRadius="5">
<ContentPresenter x:Name="contentPresenter" />
</Border>
</Border>
</ControlTemplate>
Шаблон ControlTemplate содержит две рамки. Внешняя рамка имеет имя Border, а внутренняя - задана без имени. Свойства заливки фона Background, для внешней рамки, и контура BorderBrush, для внутренней рамки, заданы в расширенной разметке ссылкой на статические ресурсы, определенные в файле ColorsAndBrushesRD.xaml.
Свойство ContentPresenter внутренней рамки интерфейсного элемента ListBoxItem определяет где должно отображаться содержание ( Content ) данного элемента.
Визуальное поведение задает способ отображения элемента управления в определенных состояниях. Для элемента управления ListBoxItem имеются следующие состояния, которые приведены в табл.7.1
Таблица 8.1. Визуальные состояния класса ListBoxItem |
||
VisualState |
VisualStateGroup |
Описание |
Normal |
CommonStates |
Состояние по умолчанию. |
MouseOver |
CommonStates |
Указатель мыши расположен в элементе управления. |
Disabled |
CommonStates |
Элемент отключен. |
Focused |
FocusStates |
На элементе установлен фокус. |
Unfocused |
FocusStates |
Элемент не имеет фокус. |
Selected |
SelectionStates |
Элемент выбран. |
Unselected |
SelectionStates |
Элемент не выбран. |
SelectedUnfocused |
SelectionStates |
Элемент выбран, но не имеет фокус. Это состояние отсутствует в шаблоне элемента управления ListBoxItem по умолчанию. Однако можно изменить ControlTemplate объекта ListBoxItem для использования этого состояния. |
BeforeLoaded |
LayoutStates |
ListBoxItem еще не загружен. |
AfterLoaded |
LayoutStates |
ListBoxItem загружен. |
BeforeUnloaded |
LayoutStates |
ListBoxItem еще не выгружен. |
Для управления состояниями и логикой переходов между состояниями элементов управления используется класс VisualStateManager, который в XAML-разметке стиля представлен одноименным свойством. Данное свойство позволяет указывать состояния для элемента управления, его внешний вид в определенном состоянии, и порядок изменения состояния элемента управления. Внешний вид элемента управления, находящегося в некотором состоянии, определяется классом VisualState. Данный класс содержит коллекцию объектов Storyboard, указывающих, как изменяется внешний вид элемента управления в определенном состоянии. Состояния просмотра добавляются в элемент управления посредством вложенного свойства зависимостей VisualStateManager.VisualStateGroups элемента управления. Для проектируемого стиля необходимо задать визуальное представление для состояний CommonStates и SelectionStates.
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
. . .
<!—Описание состояний и поведения в этих состояниях -->. . .
. . .
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
. . .
<!—Описание состояний и поведения в этих состояниях -->. . .
. . .
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
Каждый объект VisualStateGroup содержит коллекцию взаимоисключающих объектов VisualState. Элемент управления всегда находится в точности одном состоянии в каждой группе VisualStateGroup.
Для группы CommonStates определим функциональность для состояний Normal и MouseOver. При наведении указателя мыши на элемент списка ListBoxItem (состояние MouseOver ) свойство ColorAnimation определяет процесс анимации значения свойства Background (Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)") для объекта Border (Storyboard.TargetName="Border") от исходного значения к целевому (To="{StaticResource PhotoSelectedBGColor}") в указанном интервале Duration (Duration="0:0:0"). При переходе в состояние Normal, то есть, когда указатель мыши покидает элемент списка, анимация прерывается и внешняя рамка элемента списка принимаем исходный вид. XAML-разметка управления визуальным представлением элемент списка ListBoxItem для группы CommonStates приведена ниже.
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0:0:0"
To="{StaticResource PhotoSelectedBGColor}"
Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
Storyboard.TargetName="Border" />
</Storyboard>
</VisualState>
Для группы SelectionStates определим функциональность для состояний Unselected и Selected. XAML-разметка управления визуальным представлением элемент списка ListBoxItem для группы SelectionStates спроектирована аналогично приведенной выше для группы CommonStates и имеет следующий вид.
<VisualState x:Name="Unselected" />
<VisualState x:Name="Selected">
<Storyboard>
<ColorAnimation Duration="0:0:0"
To="{StaticResource ItemSelectedBGColor}"
Storyboard.TargetProperty= (Border.Background).(SolidColorBrush.Color)"
Storyboard.TargetName="Border" />
</Storyboard>
</VisualState>
Полный код XAML-разметки стиля ListBoxItemStyle приведен в приложении.
Стиль ListBoxPhotoStyle задается для типа ListBox и определяет элемент прокрутки ScrollViewer. Стиль элемент прокрутки задается ссылкой на статический ресурс ScrollViewerPhotoStyle. Полный код XAML-разметки стиля приведен в приложении.
Стиль ScrollViewerPhotoStyle задается для типа ScrollViewer (TargetType="ScrollViewer") и в нем определяются четыре свойства: HorizontalScrollBarVisibility, VerticalScrollBarVisibility, BorderThickness и Template.
<Style x:Key="ScrollViewerPhotoStyle" TargetType="ScrollViewer">
<Setter Property="HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<!—Определение вложенного свойства ControlTemplate -->
</Setter.Value>
</Setter>
</Style>
Шаблон ControlTemplate содержит два контейнера Grid. Для внешней сетки (Grid) задается свойство ScrollContentPresenter, определяющее где и как будет отображаться содержимое элемента управления ScrollViewer. Вложенная сетка имеет две колонки.
<ControlTemplate TargetType="ScrollViewer">
<Grid>
<ScrollContentPresenter
x:Name="ScrollContentPresenter"
Cursor="{TemplateBinding Cursor}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Grid.Column="1" Grid.Row="1"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!—Определение свойства ScrollBar -->
</Grid>
</Grid>
</ControlTemplate>
Элемент управления ScrollBar предоставляет полосу прокрутки с перемещаемым элементом, позиция которого соответствует значению.
<ScrollBar
x:Name="VerticalScrollBar"
Grid.Row="0" Grid.Column="1"
IsTabStop="False"
Maximum="{TemplateBinding ScrollableHeight}"
Height="250" Minimum="0"
Orientation="Vertical"
VerticalAlignment="Center"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
Value="{TemplateBinding VerticalOffset}"
ViewportSize="{TemplateBinding ViewportHeight}"
Width="18" Margin="10" HorizontalAlignment="Center"
Opacity="0.5"/>
Полный код XAML-разметки стиля ScrollViewerPhotoStyle приведен в приложении.
Шаблон данных ListBoxItemPhotoDataTemplate практически не отличается от ранее определенного шаблона для элемента listBoxEmployees, за исключением внешней и внутренней рамок. Полный код XAML-разметки шаблона данных ListBoxItemPhotoDataTemplate приведен в приложении.
Стили и шаблон для интерфейсного элемента ListBox поместим в словарь ресурсов StylesAndTemplates.xaml. Так как созданные стили ссылаются на ресурсы из файла ColorsAndBrushesRD.xaml, то данные ресурсы необходимо сделать доступными в файле StylesAndTemplates.xaml с помощью свойства MergedDictionaries словаря ResourceDictionary. Свойство MergedDictionaries представляет различные словари ресурсов в объединенных словарях.
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ColorsAndBrushesRD.xaml"/>
</ResourceDictionary.MergedDictionaries>
После создания стилей и шаблон для интерфейсного элемента ListBox необходимо модифицировать XAML-разметку для элемента listBoxEmployees главного окна приложения.
<ListBox Grid.Row="1" Name="listBoxEmployees" HorizontalAlignment="Center"
Margin="45,2,76,9" Padding="3" Width="263"
ItemContainerStyle="{StaticResource ListBoxItemStyle}"
Style="{StaticResource ListBoxPhotoStyle}"
ItemTemplate="{StaticResource ListBoxItemPhotoDataTemplate}"
Background="{x:Null}" />
После компиляции и запуска страница приложения имеет вид, приведенный на рис. 8.4.
Рис. 8.4. Страница приложения с модифицированным интерфейсным элементом списка.