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

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

Шаг 2. Добавление обработки событий клавиатуры

Для реализации функциональности "быстрых клавиш" нам необходимо осуществить реакцию на события клавиатуры, полученные элементом StackPanel, в частности событие KeyDown. Событие KeyDown является пузырьковым событием.

Мы можем начать с простого и отвечать на любые события клавиатуры путем заполнения формы адресом компании Microsoft. Присвоим классу защищенный объект (private) Address, который мы инициализируем в конструкторе. Также будем обрабатывать стандартное событие Loaded, которое вызывается при загрузке страницы.

public partial class MainPage : UserControl
{
    private Address theAddress;
    public MainPage()
    {
        InitializeComponent();
        address = new Address();
        Loaded += new RoutedEventHandler(OnLoaded);
    }

В OnLoaded мы хотим создать обработчик события для KeyDown при регистрации любого события клавиши для любого элемента управления в пределах табличной сетки, которую мы назвали AddressGrid в MainPage.xaml следующим образом,

<Grid x:Name="AddressGrid" Background="Bisque" >

При сохранении страницы MainPage.xaml данный определитель мгновенно будет доступен в фоновом коде, и мы можем получить доступ к его свойствам и событиям, включая событие KeyDown.

void OnLoaded(object sender, RoutedEventArgs e)
{
    AddressGrid.KeyDown += new KeyEventHandler(AddressGrid_KeyDown);
}

Visual Studio 2010 предложит вам создать программную оболочку для обработчика события, что нам как раз и нужно. Нам необходимо заполнить форму адресом компании Microsoft при нажатии Ctrl+M.

void AddressGrid_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.M && Keyboard.Modifiers == ModifierKeys.Control)
    {
        address.Location = "Microsoft";
        address.Address1 = "One Microsoft Way";
        address.Address2 = "Building 10";
        address.City = "Redmond, WA 98052";
    }
    this.DataContext = theAddress;
} 

Обратите внимание на то, что мы завершаем событие установкой DataContext страницы в только что заполненный объект Address. Результатом будет объект для привязки к элементам управления.

Шаг 3. Инкапсуляция разметки и логики в элемент управления UserControl

На самом деле, нам наверняка понадобится наличие домашнего адреса (Home Address), рабочего адреса (Work Address) и адреса выставления счета (Billing Address), и неплохо было бы иметь комбинацию клавиш для каждого из адресов. Это можно реализовать двумя способами:

  • продублировать xaml на стартовой странице нашего приложения и его фоновый код для каждого экземпляра (home, work, billing);
  • перестроить (инкапсулировать) ранее созданную разметку и код в независимый элемент управления (отдельный UserControl).

Разумный подход - инкапсулировать стандартный xaml и поддерживающий код в элемент управления путем создания пользовательского элемента управления (UserControl).

Добавим в проект Silverlight User Control. Назовем новый элемент управления AddressUserControl.xaml.

К проекту будут добавлены два файла

  • AddressUserControl.xaml
  • AddressUserControl.xaml.cs

AddressUserControl.xaml выглядит очень знакомо при открытии.

<UserControl x:Class="ControlsExample.AddressUserControl"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">
        …
    </Grid>
</UserControl>
Реализация элемента управления

Вернемся к MainPage.xaml и вынесем xaml разметку начиная с Border во вновь созданный UserControl, заменив табличную сетку, созданную там Visual Studio 2010.

Обратите внимание на то, что ваш элемент управления находится в правильном месте, но немного узок. Удалите атрибуты ширины (Width) и высоты (Height) и внешнего пользовательского элемента управления,

<UserControl x:Class="ControlsExample.AddressUserControl"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    > <!--no specific size-->
   <Border BorderBrush="Black"  BorderThickness="1" Margin="15"> 
          …

Как только вы удалите их, элемент управления будет выровнен по центру, а также расширен для того, чтобы вместить в себя элементы управления (рис. 9.2).

Автоматическое изменение размера пользовательского элемента управления

Рис. 9.2. Автоматическое изменение размера пользовательского элемента управления
Добавление кода

Все последующие шаги выполняются в AddressUserControl.xaml.cs: Добавляем переменную экземпляра Address так же, как и в MainPage.xaml.cs. В конструкторе выделяем память для объекта Address и настраиваем обработчик события Loaded. В реализации OnLoaded добавляем новый обработчик для события KeyDown табличной сетки.

public partial class AddressUserControl : UserControl
{
    private Address theAddress = null;
    public AddressUserControl()
    {
        InitializeComponent();
        theAddress = new Address();
        Loaded += new RoutedEventHandler(OnLoaded);
    }
    void OnLoaded(object sender, RoutedEventArgs e)
    {
        AddressGrid.KeyDown += new KeyEventHandler(AddressGrid_KeyDown);
    }

Реализация AddressGrid.KeyDown была вырезана из MainPage.xaml.cs

void AddressGrid_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.M && Keyboard.Modifiers == ModifierKeys.Control)
        
            theAddress.Location = "Microsoft";
            theAddress.Address1 = "One Microsoft Way";
            theAddress.Address2 = "Building 10";
            theAddress.City = "Redmond, WA 98052";
        }
        this.DataContext = theAddress;
    }
   }

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

Мы завершили создание пользовательского элемента управления, но от него нет толку, пока вы его не расположите в файле MainPage.xaml. В самой верхней части MainPage.xaml добавьте пространство имен для вашего AddressUserControl’a:

xmlns:controls="clr-namespace:ControlsExample"

Теперь вы можете заменить ваш пользовательский элемент управления для всего содержимого Border в MainPage.xaml. Если вы еще не удалили Border, то удалите и замените своим элементом управления, точно также как вы вставили бы любой другой элемент управления в StackPanel,

<controls:AddressUserControl x:Name="HomeAddress" />
Многократное использование

Давайте добавим еще один пользовательский элемент управления к StackPanel и изменим подсказки таким образом, чтобы у нас было следующее

<UserControl x:Class="Example.MainPage"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:controls="clr-namespace:ControlsExample"
    Width="600" Height="500">
    <StackPanel Background="White">
        <TextBlock Text="Event Address" FontFamily="Verdana" FontSize="24"
            HorizontalAlignment="Left" Margin="15,0,0,0"/>
         <controls:AddressUserControl x:Name="HomeAddress" />
       <TextBlock Text="Billing Address" FontFamily="Verdana" FontSize="24"
            HorizontalAlignment="Left" Margin="15,0,0,0"/>
         <controls:AddressUserControl x:Name="BillingAddress" />           
  </StackPanel>
</UserControl> 

Обратите внимание, что добавление второго экземпляра AddressUserControl требует только наличия двух различных названий. Более того мы смогли вынести весь код из главной страницы приложения (логика которого не относилась к MainPage.xaml.cs)

using System.Windows.Controls;
namespace Example
{
    public class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }
    }
}

Вся логика была экспортирована и инкапсулирована в пользовательском элементе управления. Вы можете добавить 2 (или 20) пользовательских элемента управления AddressUserControl в ваш интерфейс, не написав и строки кода. При этом, запустив программу, каждый элемент будет работать независимо и каждый поддерживает комбинацию Ctrl + M