Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Упражнение 2. Прослушивание событий мыши






  • Добавьте к решению командой File/Add/New Project новый проект с именем ListenerEvents и назначьте его стартовым


увеличить изображение

  • Выполните команду Project/ListenerEvents Properties... и настройте выпадающий список Output type на значение Console Application, чтобы параллельно запускались графическое и консольное окна приложения


увеличить изображение

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

  • Заполните файл разметки Window1.xaml следующим кодом
< Window x: Class=" ListenerEvents.Window1" xmlns=" https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns: x=" https://schemas.microsoft.com/winfx/2006/xaml" Title=" Window1: Маршрутизация событий" Height=" 300" Width=" 300" Background=" Red" ToolTip=" Элемент Window - Red" PreviewMouseDown=" Window_PreviewMouseDown" MouseDown=" Window_MouseDown" ButtonBase.Click=" Window_Click" > < Window.ContextMenu> < ContextMenu> < MenuItem Header=" Item1" /> < /ContextMenu> < /Window.ContextMenu> < DockPanel> < Menu DockPanel.Dock=" Top" ToolTip=" Элемент Menu - #FFD4D0C8" Background=" #FFD4D0C8" > < MenuItem Header=" File" > < MenuItem Header=" _Open" /> < MenuItem Header=" _Save" /> < MenuItem Header=" Save_As" /> < MenuItem Header=" E_xit" /> < /MenuItem> < MenuItem Header=" _Edit" > < MenuItem Header=" Cu_t" /> < MenuItem Header=" _Copy" /> < MenuItem Header=" _Paste" /> < /MenuItem> < /Menu> < Grid Width=" 220" Height=" 200" Background=" Green" ToolTip=" Элемент Grid - Green" PreviewMouseDown=" Grid_PreviewMouseDown" MouseDown=" Grid_MouseDown" ButtonBase.Click=" Grid_Click" > < UniformGrid Rows=" 3" Height=" 140" Width=" 130" Background=" Blue" ToolTip=" Элемент UniformGrid - Blue" PreviewMouseDown=" UniformGrid_PreviewMouseDown" MouseDown=" UniformGrid_MouseDown" ButtonBase.Click=" UniformGrid_Click" > < TextBlock Background=" Yellow" VerticalAlignment=" Center" TextAlignment=" Center" ToolTip=" Элемент TextBlock - Yellow" PreviewMouseDown=" TextBlock_PreviewMouseDown" MouseDown=" TextBlock_MouseDown" ButtonBase.Click=" TextBlock_Click" > Туннельное < LineBreak /> Пузырьковое < /TextBlock> < TextBlock Background=" Aqua" VerticalAlignment=" Center" TextAlignment=" Center" ToolTip=" Элемент TextBlock - Aqua" MouseEnter=" TextBlock_MouseEnter" MouseLeave=" TextBlock_MouseLeave" PreviewMouseDown=" TextBlock_PreviewMouseDown" MouseDown=" TextBlock_MouseDown" ButtonBase.Click=" TextBlock_Click" > Прямое MouseEnter < LineBreak /> Прямое MouseLeave < /TextBlock> < Button Background=" Orange" VerticalAlignment=" Center" ToolTip=" Элемент Button - Orange" PreviewMouseDown=" Button_PreviewMouseDown" MouseDown=" Button_MouseDown" Click=" Button_Click" > Генератор Click < /Button> < /UniformGrid> < /Grid> < /DockPanel> < /Window>

Обратите внимание, что все элементы, пока, мы сделали неименованными, но среда выполнения в точности определит, какой элемент возбудил или обработал событие. В названиях пунктов меню мы применили знаки подчеркивания для использования горячих клавиш, которые проявятся после нажатия клавиши Alt в работающем приложении. В Windows Forms для этой цели используется символ амперсанда &, но в XAML он конфликтовал бы с подобным управляющим символом &, поэтому был заменен на подчеркивание.

  • Заполните файл поддержки разметки Window1.xaml.cs следующим кодом
using System; using System.Collections.Generic; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace ListenerEvents{ public partial class Window1: Window { public Window1() { InitializeComponent(); } int count; private void Window_PreviewMouseDown(object sender, MouseButtonEventArgs e) { count = 0; Console.Clear(); if (e.ChangedButton == MouseButton.Left) Console.WriteLine(" {0}) Window: Наблюдаю туннельное событие PreviewMouseDown", ++count); else e.Handled = true; } private void Window_MouseDown(object sender, MouseButtonEventArgs e) { Console.WriteLine(" {0}) Window: Наблюдаю пузырьковое событие MouseDown", ++count); } private void Window_Click(object sender, RoutedEventArgs e) { Console.WriteLine(" {0}) Window: Наблюдаю пузырьковое событие Click (как вложенное)", ++count); } private void Grid_PreviewMouseDown(object sender, MouseButtonEventArgs e) { Console.WriteLine(" {0}) Grid: Наблюдаю туннельное событие PreviewMouseDown", ++count); } private void Grid_MouseDown(object sender, MouseButtonEventArgs e) { Console.WriteLine(" {0}) Grid: Наблюдаю пузырьковое событие MouseDown", ++count); } private void Grid_Click(object sender, RoutedEventArgs e) { Console.WriteLine(" {0}) Grid: Наблюдаю пузырьковое событие Click (как вложенное)", ++count); } private void UniformGrid_PreviewMouseDown(object sender, MouseButtonEventArgs e) { Console.WriteLine(" {0}) UniformGrid: Наблюдаю туннельное событие PreviewMouseDown", ++count); } private void UniformGrid_MouseDown(object sender, MouseButtonEventArgs e) { Console.WriteLine(" {0}) UniformGrid: Наблюдаю пузырьковое событие MouseDown", ++count); } private void UniformGrid_Click(object sender, RoutedEventArgs e) { Console.WriteLine(" {0}) UniformGrid: Наблюдаю пузырьковое событие Click (как вложенное)", ++count); } private void TextBlock_PreviewMouseDown(object sender, MouseButtonEventArgs e) { Console.WriteLine(" {0}) TextBlock: Наблюдаю туннельное событие PreviewMouseDown", ++count); } private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e) { Console.WriteLine(" {0}) TextBlock: Наблюдаю пузырьковое событие MouseDown", ++count); } private void TextBlock_Click(object sender, RoutedEventArgs e) { Console.WriteLine(" {0}) TextBlock: Наблюдаю пузырьковое событие Click (как вложенное)", ++count); } private void TextBlock_MouseEnter(object sender, MouseEventArgs e) { Console.WriteLine(" {0}) TextBlock: Возбуждаю прямое событие MouseEnter", ++count); } private void TextBlock_MouseLeave(object sender, MouseEventArgs e) { Console.WriteLine(" {0}) TextBlock: Возбуждаю прямое событие MouseLeave", ++count); } private void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e) { Console.WriteLine(" {0}) Button: Наблюдаю туннельное событие PreviewMouseDown", ++count); } private void Button_MouseDown(object sender, MouseButtonEventArgs e) { Console.WriteLine(" {0}) Button: Наблюдаю пузырьковое событие MouseDown", ++count); } private void Button_Click(object sender, RoutedEventArgs e) { Console.WriteLine(" {0}) Button: Возбуждаю пузырьковое событие Click", ++count); } }}

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

  • Запустите приложение - получим следующее графическое окно

 

Для элементов логического дерева, входящих в разметку, мы определили разный цвет фона, чтобы можно было их визуально различать. Цвет фона меню Background=" #FFD4D0C8" мы назначили в стиле HTML для напоминания, хотя по умолчанию оно и так имеет такой фоновый системный цвет, типичный для большинства пользовательских элементов управления (первый байт FF определяет коэффициент непрозрачности Opacity, FF - полная непрозрачность, 0 - полная прозрачность).

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

Маршрутизация событий при щелчках на элементах
Цвет (элемент) Вывод обработчиков
Red
  1. Window: Наблюдаю туннельное событие PreviewMouseDown
  2. Window: Наблюдаю пузырьковое событие MouseDown
Green
  1. Window: Наблюдаю туннельное событие PreviewMouseDown
  2. Grid: Наблюдаю туннельное событие PreviewMouseDown
  3. Grid: Наблюдаю пузырьковое событие MouseDown
  4. Window: Наблюдаю пузырьковое событие MouseDown
Blue
  1. Window: Наблюдаю туннельное событие PreviewMouseDown
  2. Grid: Наблюдаю туннельное событие PreviewMouseDown
  3. UniformGrid: Наблюдаю туннельное событие PreviewMouseDown
  4. UniformGrid: Наблюдаю пузырьковое событие MouseDown
  5. Grid: Наблюдаю пузырьковое событие MouseDown
  6. Window: Наблюдаю пузырьковое событие MouseDown
Yellow
  1. Window: Наблюдаю туннельное событие PreviewMouseDown
  2. Grid: Наблюдаю туннельное событие PreviewMouseDown
  3. UniformGrid: Наблюдаю туннельное событие PreviewMouseDown
  4. TextBlock: Наблюдаю туннельное событие PreviewMouseDown
  5. TextBlock: Наблюдаю пузырьковое событие MouseDown
  6. UniformGrid: Наблюдаю пузырьковое событие MouseDown
  7. Grid: Наблюдаю пузырьковое событие MouseDown
  8. Window: Наблюдаю пузырьковое событие MouseDown
Aqua
  1. TextBlock: Возбуждаю прямое событие MouseEnter
  2. TextBlock: Возбуждаю прямое событие MouseLeave
Orange
  1. Window: Наблюдаю туннельное событие PreviewMouseDown
  2. Grid: Наблюдаю туннельное событие PreviewMouseDown
  3. UniformGrid: Наблюдаю туннельное событие PreviewMouseDown
  4. Button: Наблюдаю туннельное событие PreviewMouseDown
  5. Button: Возбуждаю пузырьковое событие Click
  6. UniformGrid: Наблюдаю пузырьковое событие Click (как вложенное)
  7. Grid: Наблюдаю пузырьковое событие Click (как вложенное)
  8. Window: Наблюдаю пузырьковое событие Click (как вложенное)

Обратите внимание, что хотя мы и вложили в элементы TextBlock событие Click, но оно не проходит через них при щелчке на кнопке, поскольку сразу всплывает к родительскому элементу UniformGrid. И любой из элементов с вложенным событием Click, как и вообще с любым вложенным событием, способен его только слушать и обрабатывать, но никоим образом не может его возбуждать.

Может возникнуть вопрос, а как на самом деле в коде происходит регистрация обработчиков событий, если мы их прикрепили в разметке,...и с помощью каких делегатов? Все это делает за нас оболочка благодаря тому, что класс поддержки разметки объявлен как partial (частичный). Чтобы увидеть это, надо зайти в конструктор кодовой части файла Window1.axml.cs для класса Window1, щелкнуть правой кнопкой мыши на вызове метода InitializeComponent() и выбрать команду Go To Definition (Перейти к определению) из контекстного меню. В редакторе отобразится созданный файл кода Window1.g.i.cs, где и будут полные определения прикрепленных к элементам обработчиков событий.

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

private void CommonClickHandler(object sender, RoutedEventArgs e){ FrameworkElement feSource = e.Source as FrameworkElement; switch (feSource.Name) { case " YesButton": // do something here... break; case " NoButton": // do something... break; case " CancelButton": // do something... break; } e.Handled=true; }

Это распространенный прием для распознавания и обыкновенных событий C#.






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.