Последовательность обработки событий
События в UI(пользовательский интерфейс) Позволяет пользователю взаимодействовать с вашим приложением. Подробнее
См. в Словарь Инструментарий похож на HTML-события. Когда происходит событие, оно отправляется по пути распространения в дереве визуальных элементов. Событие отправляется не только целевому визуальному элементу, но и всем элементам в пределах пути распространения.
Последовательность обработки событий следующая:
- Выполнять обратные вызовы событий для элементов от корневого элемента до родительского элемента цели события. Это фаза просачивания процесса отправки.
- Выполнять обратные вызовы событий в целевом объекте события. Это целевой этап процесса отправки.
- Вызовите
ExecuteDefaultActionAtTarget()
для цели события. - Выполнять обратные вызовы событий для элементов от родительского целевого объекта события до корня. Это фаза всплытия процесса отправки.
- Вызовите
ExecuteDefaultAction()
для цели события.
По мере того, как событие перемещается по пути распространения, свойство Event.currentTarget
обновляется до элемента, обрабатывающего событие в данный момент. В функции обратного вызова события:
Event.currentTarget
– это визуальный элемент, на котором регистрируется обратный вызов.Event.target
– это визуальный элемент, в котором происходит исходное событие.
Дополнительную информацию см. в разделе Отправка событий.
Регистрация обратного вызова события
Регистрация обратного вызова события позволяет настраивать поведение отдельного экземпляра существующего класса, например реагировать на щелчок мыши по текстовой метке.
Каждый элемент на пути распространения (кроме целевого) может получить событие дважды:
- Один раз на этапе просачивания.
- Один раз на этапе всплытия.
По умолчанию зарегистрированный обратный вызов выполняется во время целевой фазы и фазы всплывающей подсказки. Это поведение по умолчанию гарантирует, что родительский элемент реагирует после своего дочернего элемента. Например, если вы хотите, чтобы родительский элемент реагировал раньше своего дочернего элемента, зарегистрируйте обратный вызов с параметром TrickleDown.TrickleDown
:
// Регистрируем обратный вызов для фазы просачивания
myElement.RegisterCallback(MyCallback, TrickleDown.TrickleDown);
Это информирует диспетчера о необходимости выполнить обратный вызов на целевой фазе и фазе просачивания.
Чтобы добавить пользовательское поведение к определенному визуальному элементу, необходимо зарегистрировать обратный вызов события для этого элемента. Например, следующий код регистрирует обратный вызов для MouseDownEvent
:
// Регистрируем обратный вызов на событие нажатия кнопки мыши
myElement.RegisterCallback(MyCallback);
Ваша подпись обратного вызова должна выглядеть следующим образом:
void MyCallback(MouseDownEvent evt) { /* ... */ }
Для события можно зарегистрировать несколько обратных вызовов. Вы можете зарегистрировать одну и ту же функцию обратного вызова для одного и того же события и фазы распространения только один раз. Чтобы удалить обратный вызов из VisualElement
, вызовите метод myElement.UnregisterCallback()
.
Добавление пользовательских данных в обратный вызов события
Вы можете отправлять пользовательские данные вместе с обратным вызовом для события. Чтобы прикрепить пользовательские данные, необходимо расширить вызов, чтобы зарегистрировать обратный вызов.
Следующий код регистрирует обратный вызов для MouseDownEvent
и отправляет пользовательские данные в функцию обратного вызова:
// Send user data along to the callback
myElement.RegisterCallback(MyCallbackWithData, myData);
Функция обратного вызова должна возвращать эту подпись:
void MyCallbackWithData(MouseDownEvent evt, MyType data) { /* ... */ }
Реагирование на события с помощью настраиваемых элементов управления
Если вы внедряете настраиваемые элементы управления, вы можете реагировать на события UI Toolkit двумя способами:
- Регистрация обратного вызова события.
- Реализация действия по умолчанию.
Как вы решите реагировать на события, зависит от ситуации.
Разница между обратными вызовами и действиями по умолчанию заключается в следующем:
- Обратные вызовы должны регистрироваться в экземплярах класса. Действия по умолчанию выполняются как виртуальные функции класса.
- Обратные вызовы выполняются для всех визуальных элементов на пути распространения. Действия по умолчанию выполняются только для цели события.
- Обратные вызовы могут выполнять дополнительные проверки, чтобы определить, должны ли они реагировать на событие. Например, обратный вызов, обрабатывающий щелчок мышью, может проверить, является ли элемент целью события. В действиях по умолчанию этот шаг можно пропустить.
- Действия по умолчанию имеют небольшое преимущество в производительности, поскольку они не требуют поиска в реестре обратных вызовов на этапе распространения.
Реализация действия по умолчанию
Действие по умолчанию применяется ко всем экземплярам класса. Класс, который реализует действия по умолчанию, также может иметь обратные вызовы, зарегистрированные в его экземплярах.
Когда класс реализует действие по умолчанию, он должен быть производным от нового подкласса VisualElement
и реализовать либо ExecuteDefaultActionAtTarget()
метод, метод ExecuteDefaultAction()
или оба метода.
Действия по умолчанию выполняются для каждого экземпляра подкласса визуального элемента, когда этот экземпляр получает событие. Чтобы настроить действия по умолчанию, вы можете переопределить ExecuteDefaultActionAtTarget()
и ExecuteDefaultAction()
, как показано в примере ниже:
override void ExecuteDefaultActionAtTarget(EventBase evt)
{
// Call the base function.
base.ExecuteDefaultActionAtTarget(evt);
if (evt.GetEventTypeId() == MouseDownEvent.TypeId())
{
// ...
}
else if (evt.GetEventTypeId() == MouseUpEvent.TypeId())
{
// ...
}
// More event types
}
Реализация действий по умолчанию в ExecuteDefaultAction()
позволяет остановить или предотвратить выполнение действия по умолчанию.
Если вы хотите, чтобы целевое действие по умолчанию выполнялось до обратного вызова его родительского объекта, реализуйте действия по умолчанию в ExecuteDefaultActionAtTarget()
.
Вы должны рассматривать действия по умолчанию как поведение, которое должен иметь тип элемента, когда он получает событие. Например, флажок должен изменять свое состояние в ответ на событие щелчка. Чтобы выполнить это, вы можете переопределить виртуальную функцию действия по умолчанию вместо регистрации обратных вызовов для всех флажков.
Рекомендации по использованию настраиваемых элементов управления
Реализация поведения
Вы должны реализовать поведение вашего элемента с действиями по умолчанию. Вы можете вызвать PreventDefault()
в обратном вызове, прикрепленном к экземпляру, чтобы отменить поведение элемента по умолчанию.
Дополнительные преимущества реализации поведения в качестве действий по умолчанию:
- Действия по умолчанию не требуют поиска в реестре обратных вызовов.
- Экземпляры без обратных вызовов не участвуют в процессе распространения.
Для большей гибкости вы можете выполнять действия по умолчанию цели события в два момента во время процесса отправки события:
- Между фазами распространения и распространения, сразу после выполнения целевых обратных вызовов, переопределить
ExecuteDefaultActionsAtTarget()
. - В конце процесса отправки события переопределите
ExecuteDefaultActions()
.
Действия по умолчанию для класса
Если возможно, реализуйте действия по умолчанию вашего класса в ExecuteDefaultActions()
. Это дает больше возможностей для переопределения класса. Вы можете вызвать PreventDefault()
, чтобы переопределить класс во время фазы просачивания вниз или фазы всплытия процесса распространения события.
Вы должны остановить распространение события во время действия по умолчанию, если событие не должно распространяться на родительский элемент. Например, текстовое поле получает событие KeyDownEvent
, которое изменяет его значение, например клавишу Delete
для удаления содержимого. Это событие не должно распространяться на родительский визуальный элемент. Используйте ExecuteDefaultActionsAtTarget()
для реализации действия по умолчанию и вызовите StopPropagation()
, чтобы убедиться, что событие не обрабатывается во время фаза всплытия.
Действия по умолчанию выполняются только для цели события. Чтобы класс реагировал на события, которые нацелены на его дочерние или родительские элементы, вы должны зарегистрировать обратный вызов для получения события либо во время фазы просачивания, либо во время фазы распространения всплывающей подсказки. Избегайте регистрации обратных вызовов в своем классе, чтобы повысить производительность.
Остановка распространения событий и отмена действий по умолчанию
При обработке события внутри обратного вызова или действия по умолчанию вы можете остановить дальнейшее распространение события и выполнение действий по умолчанию. Например, родительская панель может остановить распространение на этапе просачивания, чтобы ее дочерние элементы не получали события.
Вы не можете предотвратить выполнение методов EventBase.PreDispatch()
и EventBase.PostDispatch()
внутри сам класс события.
Следующие методы влияют на распространение события и действия по умолчанию:
StopImmediatePropagation()
- Stops the event propagation process immediately, so no other callbacks execute for the event. However, the
ExecuteDefaultActionAtTarget()
andExecuteDefaultAction()
default actions still execute.
StopPropagation()
- Остановка процесса распространения события после последнего обратного вызова для текущего элемента. Это гарантирует, что все обратные вызовы выполняются для текущего элемента, но никакие другие элементы не реагируют на событие. Действия по умолчанию
ExecuteDefaultActionAtTarget()
иExecuteDefaultAction()
по-прежнему выполняются.
PreventDefaultAction()
- Предотвращает вызов процессом распространения события действий по умолчанию
ExecuteDefaultActionAtTarget()
иExecuteDefaultAction()
.PreventDefaultAction()
не предотвращает выполнение других обратных вызовов и неэффективен дляExecuteDefaultActionAtTarget()
при вызове во время всплывающего окна. фаза вверх.