• Microsoft .NET
  • WPF и Silverlight
  • Элементы управления пользовательского интерфейса Silverlight (User Interface Controls)

Элементы управления пользовательского интерфейса Silverlight (User Interface Controls) - События элементов управления и их обработчики

ОГЛАВЛЕНИЕ

События элементов управления и их обработчики

В Silverlight 2 каждый класс объявляет о том, поддерживается ли он управляемым кодом или нет путем включения (либо исключения) атрибута x:Class в его корневом элементе. Данные статьи подразумевают, что вы работаете с управляемым кодом, и, следовательно, данный атрибут присутствует.

Когда вы создаете управляемый код приложения Silverlight в Visual Studio, атрибут Class будет расположен автоматически, без вашего участия . Создайте новое приложение и назовите его EventHandler, и затем исследуйте первые пару строк, как это показано ниже,

<UserControl x:Class="EventHandler.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">

Объявление обработчиков событий

Существует два способа объявить обработчики событий в Silverlight: в файле Xaml или в фоновом коде. Если вы объявите обработчики событий в Xaml, то вы не сможете добавлять параметры. Обычным объявлением обработчика события в XAMl будут следующие строки

<Canvas Loaded="Canvas_Loaded">
  <Button x:Name="myButton" Content="Hello"
    Canvas.Left="10" Canvas.Top="10" />
</Canvas> 

Здесь я удалил элемент Grid, созданный Visual Studio, и объявил объект Canvas. Я также назначил обработчик события, названный "Canvas_Loader" к загружаемому (Load) событию (стандартному событию, вызываемому при запуске (создании) Canvas).

Затем я объявляю кнопку в Xaml и устанавливаю содержимое в Hello.

Данный код появляется в Page.xaml. В файле с фоновым кодом Page.xaml.cs я должен теперь реализовать обработчик события с именем, которое я обещал использовать,

private void Canvas_Loaded(object sender, RoutedEventArgs e)
{
 myButton.Content = "Please Click Me";

Первое, на что следует обратить внимание, это то, что метод является идентичным тому, который объявлен в Xaml. Во-вторых, этот метод следует шаблону всех обработчиков события .NET. Он совершает возврат (наподобие void) и получает два параметра: первый - вроде object (содержащий ссылку на объект,вызвавший собитие), и второй- вроде EventArgs или вроде унаследованного от EventArgs; в данном случае RoutedEventArgs. Мы скоро вернемся к RoutedEventArgs.

Реализация заключается в том, что при загрузке Canvas, он выхватывает кнопку, объявленную в файле Xaml, и изменяет его свойство Content с "Hello" на "Please, push me",

Рис. 1-12. Измененнное свойство содержимого

Даже в данном необычайно простом примере есть две важные вещи на которые необходимо обратить внимание:

  1.  Вам не надо было объявлять myButton в фоновом коде; оно было получено объявлением в Xaml.
  2. Кнопка изменила свои размеры для того, чтобы занять большую строку.

Объявление обработчиков событий в коде

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

В любом случае, если вы хотите объявить ваши обработчики событий правильно в коде, то с Visual Studio это очень просто. Самым обычным способом будет привязка обработчиков событий в обработчике событий OnLoaded, с этим событием (Loaded) привязанным в конструкторе страницы (Page).

Чтобы увидеть это все в действии вернемся к предыдущему коду и уберем обработчик события из Xaml. Добавьте СheckBox как это показано ниже,

<!-- <Canvas Loaded="Canvas_Loaded"> -->
<Canvas >
  <Button x:Name="theButton" Content="I'm Indented!"
    Canvas.Left="150" Canvas.Top="20" />
    
  <CheckBox x:Name="RushOrder" Content="Rush"
    Canvas.Left="50" Canvas.Top="20" FontSize="18" />
</Canvas> 

Заметьте, что оригинальный Canvas закомментирован и заменен элементом Canvas, который не имееет событий.

Сохраните файл Xaml и откройте фоновый класс.

В конструкторе напишите Lo. Выскочит Intellisense и предложит вам в помощь создать код для события Loaded, что вам как раз и нужно. Подсказка (рядом с окошком Intellisence) показывает тип события.

Рис. 1-13. Intellisense помогает в создании обработчика событий

Мы скоро вернемся к тому факту, что Loaded является RoutedEventHandler. Нажмите кнопку табуляции и выберите Loaded, напечатайте += для того, чтобы начать добавлять делегатов. Если делегаты и события являются новшеством для вас, то вы можете в любой книжке по .NET 3.5, C# или VB найти и прочитать различные источники по делегатам и событиям.

Intellisense проведет вас через все шаги привязывания к обработчику события и если вы ему позволите, то и создаст основу метода обработчика события, в конце расположив курсор в методе, который он заполнит исключением (в случае если вы забыли добавить значимую реализацию.)

public Page()
{
 InitializeComponent();
 Loaded += new RoutedEventHandler(Page_Loaded);  
}
 
void Page_Loaded(object sender, RoutedEventArgs e)
{
 throw new NotImplementedException();
}

Удалите исключение и зарегистрируйте обработчики событий из обычных событий для вашей кнопки (Сlick) и кнопки с независимой фиксацией CheckBox (Checked и Unchecked)

void Page_Loaded(object sender, RoutedEventArgs e)
{
     myButton.Click += new RoutedEventHandler(myButton_Click);
     RushOrder.Checked += new RoutedEventHandler(RushOrder_Changed);
     RushOrder.Unchecked += new RoutedEventHandler(RushOrder_Changed);

Будьте осторожны, Intellisense захочет назвать методы для Checked и Unchecked соответственно RushOrder_Checked и RushOrder_Unchecked, но нет никакой необходимости в двух методах. Мы перегрузим это путем написания имени, которое нам необходимо, RushOrder_Changed, которое заставит оба обработчика события использовать разделяемый обработчик события.

В разделяемом обработчике событий мы проверим статус IsChecked кнопки с независимой фиксацией и если она выбрана, то мы изменим текст в верхний регистр (просто для того, чтобы убедиться, что обработчик события работает).

void RushOrder_Changed(object sender, RoutedEventArgs e)
{
  if (RushOrder.IsChecked == true)
  {
  RushOrder.Content = "RUSH";
  }
  else
  {
  RushOrder.Content = "Rush";
  }

Заметка для программистов C#: мы должны писать

if (RushOrder.IsChecked == true)

а не

if (RushOrder.IsChecked)

потому, что IsChecked является новым логическим типом C# 3.0 ( bool?) , который подразумевает не два, а три возможных состояния: true, false или null.