Как классы и элементы управления .NET порождают и обрабатывают события, точно так же вы будете делать это и в WPF. Но библиотеки WPF принесли важное улучшение стандартных событий: мы называем их перенаправленными событиями.
Рассмотрим простой пример: у нас есть элемент управления, Button, который состоит из фонового изображения и некоего текста (рис. 16.19). Если вы вспомните наше обсуждение шаблона элемента управления и визуального дерева элементов, то это означает, что на самом деле у нас есть несколько дискретных элементов, которые составляют данную кнопку: это TextBlock, Image, а также рамка и фон кнопки.
Рис. 16.19. Кнопка с несколькими элементами
Это отдельные объекты/элементы. Поэтому ситуация с событиями несколько осложняется. Недостаточно реагировать на щелчок по фону кнопки; нам нужно также реагировать на щелчок по тексту кнопки или по ее изображению. Именно здесь в действие вступают перенаправленные события. Перенаправленные события могут вызывать обработчики событий выше или ниже по визуальному дереву элементов. Это означает, что мы можем реализовать обработчик события на уровне Button и быть уверенными в том, что щелчок по изображению или тексту кнопки будет всплывать вверх до тех пор, пока не найдет наш обработчик события.
Маршрутизированные события в WPF разделяются на три категории: восходящие, нисходящие и прямые:
□ восходящие — эти события путешествуют вверх по визуальному дереву элементов, начиная с исходного получающего событие элемента;
□ нисходящие — эти события стартуют с верха визуального дерева элементов и двигаются вниз до тех пор, пока не достигнут получающего событие элемента;
□ прямые — это эквивалент "стандартных" событий .NET: вызывается только обработчик события для получающего событие элемента.
Сами по себе события (как и почти все остальное в WPF) могут быть объявлены в XAML или в коде. Вот кнопка с определенным в ней событием MouseEnter:
<Button MouseEnter="buttonl_MouseEnter" Height="23" Name="buttonl"
Width="75">OK</Button>
Обработчик события (на языке С#) выглядит так же, как и любой другой обработчик события .NET:
private void buttonl_MouseEnter(object sender, MouseEventArgs e)
{
MessageBox.Show("MouseEnter on buttonl");
Мы только слегка затронули некоторые основные программные концепции WPF. Однако теперь вы должны обладать уже достаточными знаниями для того, чтобы суметь написать простое приложение WPF. Давайте мы именно это и сделаем (используя имеющиеся в Visual Studio 2008 инструменты).
Создание простого приложения для просмотра изображений
Для иллюстрации той роли, которую Visual Studio играет в разработке WPF-приложений, мы создадим приложение с нуля. Исходя из принципа "опыт прежде всего", давайте для данного приложения выберем то, что может выиграть от использования сильных сторон WPF (визуализации, компоновки элементов управления и шаблонов).
Рассмотрим приложение для просмотра изображений. Мы можем использовать его для просмотра списка контрольных изображений, а после выбора контрольного изображения просмотреть само изображение и даже произвести в нем изменения.
Мы будем стремиться к примерному дизайну, показанному на рис. 16.20.
Рис. 16.20. Эскиз пользовательского интерфейса приложения для просмотра изображений
Вот наши основные требования:
□ когда приложение загружается, оно производит анализ изображений, содержащихся в указанном каталоге;
□ в списке будут показаны все изображения; в списке будут показаны только контрольные изображения (без текста);
□ когда пользователь щелкает по одному из элементов списка, то область просмотра изображения заполняется выбранным изображением;
□ после этого пользователь может манипулировать изображением: можно сделать его черно-белым, изображение можно повернуть по часовой стрелке или против нее, его можно перевернуть или отразить зеркально;
О вообще, мы будем пытаться использовать WPF везде (где это возможно), для того чтобы приложение выглядело визуально убедительно; стандартное серое приложение — это не то, чего мы хотим здесь добиться.