Спонсор: Microsoft
Опубликован: 13.12.2011 | Доступ: свободный | Студентов: 981 / 29 | Оценка: 4.29 / 4.57 | Длительность: 13:56:00
Лекция 7:

Пользовательские элементы управления

Аннотация: В лекции вы увидите как создавать пользовательские элементы управления и делать их полноценными "гражданами" сообщества классов WPF и Silverliht проектов. Это значит, что вы будете оснащать их свойствами зависимости, чтобы получить поддержку таких важных служб, как привязка данных, стили и анимация. Кроме того, вы узнаете, как создать элемент, лишенный внешнего вида — управляемый шаблонами элемент, который позволяет его потребителю применять различные визуальные представления для большей гибкости.

Цель лекции: показать реализацию пользовательского элемента управления двумя путями: через UserControl и CustomControl. Дать представление о том, какой из вариантов целесообразно использовать в той или иной ситуации. Научить пользоваться свойствами зависимости. Закрепить применение стилей и шаблонов.

UserControl или CustomControl?

Есть две категории разработчиков элементов управления. Одни создают пользовательские элементы (UserControl), другие – нестандартные (CustomControl). Названия относятся к двум совершенно разным ситуациям и многие считают эти именования не совсем удачными. Некоторые программисты предпочитают такое определение: пользовательские элементы (UserControl) – как способ инкапсуляции частей графического интерфейса, а нестандартные (CustomControl) – это повторно используемые элементы, которые можно применять и в других приложениях. Вопрос о том, где проходит граница между ними, – источник ожесточенных споров.

Из вышенаписанного можно заключить, что UserControl не очень хорошо подходит для повторного использования в рамках нескольких приложений. CustomControl по сравнению с UserControl трудоемок для разработки, но предоставляет больше возможностей тонкой настройки и поддержки повторного использования.

Также программист должен помнить о том, что имеется большая вероятность возникновения ситуации, когда потребуется создать наследника от уже созданного UserControl’a, сделать это невозможно, поэтому вам придется переделывать UserControl в CustomControl. Процесс рутинный и трудоёмкий. Именно поэтому при создании пользовательского элемента управления необходимо предварительно рассмотреть все варианты его дальнейшего жизненного цикла. И если возникнут сомнения, что использовать - UserControl или CustomControl, оптимальным решением будет выбор в пользу использования CustomControl.

UserControl

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

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

Одним из способов создания пользовательских элементов управления является явное добавление его к вашему приложению. Щелкнув правой кнопкой мыши по проекту и выбрав Add->New Item, вы получите диалоговое окно, которое предложит вам шаблон с пользовательским элементом управления в качестве одной из опций.

Шаг 1. Создание повторно используемой функциональности

Повторное использование функциональности пригодно в том случае, если данная функциональность стоит того, чтобы ее еще раз использовали. Мы начнем c создания формы (рис. 9.1) как совокупности элементов управления расположенных на странице и закончим выносом повторно используемого кода в отдельный UserControl. Создаваемая форма будет иметь возможность заполнения вручную, а также поддерживать клавишную комбинацию "быстрого вызова", в частности Ctrl-M будет добавлять адрес Microsoft.

Адресная форма, заполненная посредством нажатия Ctrl-M

Рис. 9.1. Адресная форма, заполненная посредством нажатия Ctrl-M

Рассмотрим XAML разметку адресной формы, которую мы пока разместим на главной странице Silverliht приложения (MainPage). Подразумевается, что первым элементом управления будет StackPanel, поэтому мы можем с легкостью расположить элементы управления один над другим, а в пределах StackPanel у нас Grid в котором располагаются стандартные элементы управления.

<UserControl x:Class="Example.MainPage"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="500" Height="500">
   <Border>
    <StackPanel Background="White">
      <TextBlock Text="Home Address" FontFamily="Verdana" FontSize="24"
                 HorizontalAlignment="Left" Margin="15,0,0,0"/>
     <Grid x:Name="AddressGrid" >
         <!--More Here-->
     </Grid>
   </StackPanel>
  </Border>      
</UserControl>
Устанавливаем стили для элементов управления

Табличная сетка (Grid) будет заполнена четырьмя подсказками и четырьмя текстовыми полями ввода, но они все настроены вручную, и пока нас это устраивает. Приведенный ниже код должен располагаться в файле App.xaml в теги Application.Resources. Каждый Style определяет свой TargetType (т.е., Button или TextBlock) и затем устанавливает значение для каждого свойства, стилем которого оно хочет управлять. Мы создаем всего 2 стиля - один для TextBlock, который будет использован в качестве ярлыков, и второй - для получения информации в TextBox. Все TextBlocks будут выровнены по нижнему (Bottom) и левому (Left) краю, и у них будет установлен шрифт Verdana, размер шрифта 18, а текст будет синего цвета. Данные элементы TextBlock также будут иметь отступ в 5 пикселей со всех сторон

    <Application.Resources>
        <Style TargetType="TextBlock" x:Key="TextBlockPrompt">
            <Setter Property="VerticalAlignment" Value="Bottom" />
            <Setter Property="HorizontalAlignment" Value="Left" />
            <Setter Property="FontFamily" Value="Verdana" />
            <Setter Property="FontSize" Value="18" />
            <Setter Property="FontWeight" Value="Medium" />
            <Setter Property="Foreground" Value="Blue" />
            <Setter Property="Margin" Value="5" />
        </Style>
    </Application.Resources>

Все элементы TextBox будут иметь черный жирный шрифт Verdana размера 18, а также будут выровнены по нижнему левому краю. TextBox будет размером 250 на 30 и также будет иметь отступ в 5 пикселей со всех сторон.

        <Style TargetType="TextBox" x:Key="TextBoxStyle">
            <Setter Property="FontFamily" Value="Verdana" />
            <Setter Property="FontSize" Value="18" />
            <Setter Property="FontWeight" Value="Bold" />
            <Setter Property="Foreground" Value="Black" />
            <Setter Property="VerticalAlignment" Value="Bottom" />
            <Setter Property="HorizontalAlignment" Value="Left" />
            <Setter Property="Width" Value="250" />
            <Setter Property="Height" Value="30" />
            <Setter Property="Margin" Value="5" />
        </Style>
    </Application.Resources>

Вместо добавления информации о стиле TextBlock вручную, мы можем привязать информацию об атрибуте Style при помощи "key" для определения желаемого стиля.

<TextBlock Text="Location: "
     Style="{StaticResource TextBlockPrompt}"
     Grid.Row="2" Grid.Column="1"  /> 

Строка Style="{StaticResource TextBlockPrompt}" переходит в App.xaml и находит стиль, ключом которого является TextBlockPrompt, и присваивает все значения разом. Точно так же мы можем присвоить все значения стиля TextBox привязанному текстовому полю.

<TextBox x:Name="Location"
    Style="{StaticResource TextBoxStyle}"
    Text ="Silverlight Central"
    Grid.Row="2" Grid.Column="3" />

Оставшиеся элементы в разметке сопоставимы, к ним так же применяем стиль.

Двусторонняя привязка данных

Одним из мощных способов привязки данных, который поможет привязать данные об адресе, например из базы данных, XML-файла или какого-либо другого хранилища данных, является использование бизнес-объекта в качестве посредника между хранилищем и пользовательским интерфейсом. Давайте создадим объект для адреса, сопоставимый с данными, которые мы хотим отобразить (несмотря на то, что обычный бизнес-объект, скорее всего, не будет так тесно связан с конкретной страницей пользовательского интерфейса). В таблице 7.1 представлены свойства и переменные класса Address:

Таблица 9.1. Структура класса Address
Private Member Variable Public Property
Location Location
address1 Address1
address2 Address2
City City

Структура класса будет похожа на структуру, используемую в лекции о привязке данных.

using System.Collections.Generic;
using System.ComponentModel;

namespace Example
{
    public class Address : INotifyPropertyChanged
    {

Не забывайте, что каждое свойство кроме своей переменной обладает своим методом для получения данных (Get) и методом установки данных (Set), которые также вызывают событие notification.

Заменим все явно заданные значения Text Block привязанными значениями

<TextBox x:Name="Location"
    Style="{StaticResource TextBoxStyle}"
    Text ="{Binding Location, Mode=TwoWay}"
    Grid.Row="2" Grid.Column="3" />

…

В оставшихся элементах так же заменяем явно заданные значения.

Анатолий Гречман
Анатолий Гречман
Казахстан, Экибастуз, Экибастузский Инженерно-технический Институт, 2014