Пользовательские элементы управления
Шаг 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).
Добавление кода
Все последующие шаги выполняются в 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