RoutedEvents в Silverlight
То, что объяснялось выше, полностью работает в WPF, но в Silverlight имеются небольшие отличия. Вот наиболее важные из них:
• В Silverlight вы не можете создавать пользовательские RoutedEvents. В WPF для создания пользовательского события этого типа вы можете использовать EventManager, но в Silverlight это невозможно. Существует способ обойти это ограничение, но мы поговорим об этом немного позже.
• В Silverlight поддерживается только всплывающий тип событий. Это такие события, как MouseLeftButtonDown и MouseLeftButtonUp.
• Специфические для определенных контролов события не «всплывают», например событие Click контрола Button. И это довольно логично, ибо зачем распространять событие по дереву элементов, если оно может быть обработано только определенным видом контролов?
Вот небольшой пример (и исходный код к нему), который продемонстрирует поведение всплывающих событий в Silverlight. В примере я использовал события MouseLeftButtonUp и MouseLeftButtonDown.
Когда я обрабатываю событие MouseLeftButtonUp я вывожу имя контрола, поймавшего это событие в информационный список, а по событию MouseLeftButtonDown я очищаю этот список. При обработке обоих этих событий в контроле ListBox я выставляю их свойство handled в true, поскольку мне не нужно, чтобы события, порожденные этим контролом, распространялись дальше по дереву элементов. Тоже самое я сделал для обработчика события MouseLeftButtonDown, т.к. список не нуждается более, чем в одной очистке.
Замечание! Используйте маршрутизируемые события только там, где это необходимо и не забывайте останавливать такие события, если нет нужды распространять их по все дереву элементов, поскольку это может привести к логическим ошибкам в результате ложных срабатываний обработчиков других контролов. Допустим, LayoutRoot прослушивает события порожденные определенным элементом визуального дерева (прямоугольником), но это же событие может быть порождено любым другим элементом дерева (например, в LixtBox). Если мы позволим событию, порожденному в ListBox распространиться до LayoutRoot, тогда оно будет им поймано, что приведет к некорректному поведению приложения.