Что такое object routed
«Object Routed» на Алиэкспресс — что значит, перевод на русский язык
Неопытные покупатели китайских товаров часто впадают в ступор при отслеживании заказов с AliExpress. Многочисленные статусы, количество которых растет по мере приближения посылки к вам – с ходу сложно сориентироваться! Сегодня мы поговорим о статусе «Object Routed», которых некоторых клиентов Алиэкспресс может смутить. Сразу скажем, что в нем ничего страшного.
Статус «Object Routed» на AliExpress – что означает
Для правильного понимания статуса, его необходимо корректно перевести на наш язык.
На русском языке он звучит как «Объект перенаправлен». Под объектом подразумевается ваш заказ. Какой-то важной информации для клиента статус не несет. Он, можно сказать, больше технический.
Вас не должен настораживать тот факт, что «Object Routed» актуален в течение нескольких дней или даже недели. Это нормально, посылка в любом случае продолжит движение.
Для новых покупателей из РФ и СНГ в мобильном приложении
Сменить «Объект перенаправлен» должен статус «Передано на международную перевозку». В данном случае можно только порадоваться. Посылка находится еще в Китае, однако, она прошла все проверки, вскоре покинет местный сортировочный центр, отправившись в вашу страну.
Подпишись на наш Telegram — @ali_space ❤️
Будь первым, кто узнает о новых промокодах и скидках на AliExpress!
В других случаях заказу присваивается Object Routed, если он находится в транзитной стране. Например, Литве. Данный факт сути не меняет. Посылка продолжит движение, о чем будет говорить статус «Принято почтой для магистральной перевозки».
Данный статус покупатели наблюдают при оформлении заказа через AliExpress стандартная доставка. Так как это самая популярная служба доставки, неудивительно, что с обсуждаемым статусом столкнулись многие. Воспринимайте «Object Routed» следует как движение посылки по Китаю.
К сожалению, некоторые покупатели поделились информацией, что статус «Object Routed» зависает навсегда. Однако, посылка все равно благополучно приходит, теряется лишь возможность ее отслеживать. Вероятнее всего, это технический сбой, который вскоре будет устранен.
Для новых покупателей из РФ и СНГ в мобильном приложении
Сколько ждать посылку при статусе «Object Routed»
Мы не можем дать корректный ответ на данный вопрос. Существует огромное количество факторов, из которых складывается срок доставки. Начиная от загруженности складов, сортировочных центров, заканчивая тем, насколько эффективно и безошибочно работает персонал служб доставки.
Вдобавок, посылка все еще в Китае, что усложняет выяснение примерного срока доставки. Поэтому можем порекомендовать только продолжать отслеживать свою посылку и не воспринимать «Object Routed» негативно. Ваша посылка в пути, значит, обязательно доберется до получателя!
Что такое роутинг или маршрутизация простыми словами для чайников
Роутинг — это сложный механизм передачи данных
Роутинг бывает разный, например, различают два основных вида роутинга:
Прямой роутинг — это когда данные могут передаваться внутри одной сети, минуя IP-маршрутизацию. При таком подходе перед отправкой данных узел отправителя проверяет, находится ли получатель с ним в одной сети. И если это так, тогда отправитель отправляет на адрес получателя необходимый пакет данных. Для «определения адреса» в таком подходе есть даже собственный протокол ARP (Address Resolution Protocol).
Косвенный роутинг — это когда пакеты с данными передаются между разными IP-сетями. В этом случае при передаче пакетов есть «посредник», он же маршрутизатор, он же роутер. При таком подходе отправитель передает пакет с данными маршрутизатору, а тот уже доставляет данные по нужному адресу.
Что должен выяснить роутер, чтобы отправить данные:
Таблицы роутинга
Таблица роутинга — это таблица с данными, которая хранится внутри базы данных самого роутера. Такие таблицы содержат:
Адрес шлюза — это адрес самого роутера и других роутеров, на которые отправляются пакеты с данными.
Интерфейс — это физические порты, по которым осуществляется движение пакетов.
Метрику — числовое значение, определяющее приоритет маршрута.
Маску подсети — это битовое значение, которое помогает определить по заданному IP-адресу адреса отдельных узлов подсети и адрес самой подсети.
Сетевой адрес — это ID устройства, подключенного к общей сети.
Как записываются данные в таблицу?
Этот вопрос можно перефразировать так: «Как и кем составляются маршруты при передач е данных?». Маршрут может задаваться 3-мя способами:
Роутер сам прописывает маршрут передачи и осуществляет записи в таблицу. Такой способ применим по «прямому маршруту», когда передача данных осуществляется внутри одной сети.
Маршруты можно прописать «вручную». При таком подходе прописывается адрес следующего соседнего роу те ра, которому передаются пакеты данных, а он уже распределяет их по подключенным к нему сетям.
Маршруты прописываются автоматически, используя протоколы маршрутизации. Данные протоколы самостоятельно отслеживают изменения в компоновке сети и вносят соответствующие коррективы в таблицу маршрутов.
Как рассчитывается маршрут роутинга
При расчете метрик маршрута бер у тся во внимание:
возможности полосы пропускания;
время, необходимое для перемещения пакета от отправителя к получателю;
загруженность канала передачи информации в момент времени;
насколько надежен потенциальный канал передачи, то есть есть ли в нем какие-либо ошибки;
потенциальное количество переходов между роутерами.
Сравнивая все описанные свойства маршрута, роутер задает этому маршруту определенное числовое значение. Данное числовое значение принадлежит только этому маршруту и вносится в таблицу маршрутов в графу «Метрика». И если для передачи данных буд е т доступно несколько маршрутов, то роутер выберет тот, у которого будет меньшее число метрики.
Заключение
Мы будем очень благодарны
если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.
Subnets.ru blog
Сети, настройка оборудования, сетевые сервисы.
Объекты БД RIPE (ripe.net): mntner, as-set, aut-num, route, inetnum, person, domain, role
Раз вы добрались до конфигурации протокола BGP значит «общения» с базой данных (далее просто « БД «) RIPE вам не избежать.
В этой статье я попытаюсь рассказать о том, какие объекты в этой БД вам необходимы для запуска и как они используются.
Итак, вы прошли процесс получения статуса LIR, собственного блока IP-адресов и номера автономной системы (ASNum).
Справка:
Локальный Интернет-реестр (LIR – Local Internet Registry) – термин, используемый для описания членов RIPE NCC.
Их называют локальными Интернет-реестрами (LIR) потому что они несут ответственность за распределение адресного пространства и регистрацию адресного пространства на локальном уровне.Локальные Интернет-реестры также утверждают общеобязательные политики и процедуры на локальном уровне. Организации, которые становятся локальными Интернет-реестрами — это в основном Интернет-провайдеры (ISP), которые выделяют и назначают адресное пространство своим клиентам, телекоммуникационные организации и коммерческие предприятия наряду с академическими учреждениями. Академические учреждения – это организации, которым требуются большие блоки адресного пространства, которые не могут быть получены у вышестоящего провайдера.
ALLOCATION vs ASSIGNMENT
Для начала разберем два понятия:
С первым вроде все понятно, RIPE выделил вам какой-то блок для дальнейшего использования, а вот со вторым не все так просто.
Советы по заполнению ADDRESS PLAN :
Вы заполнили ADDRESS PLAN и отправили его в RIPE… ждем ответа… варианта два:
Использовать то вы его сможете, но если у вас кончится адресное пространство и вы заходите получить ещё блок адресов, то RIPE откажет вам, сославшись на то, что вы в текущий момент не используете свой первый ALLOCATED блок адресов. Посмотреть как RIPE видит текущее ваше использование выделенного вам адресного пространства можно с помощью утилиты Web Asused, указав свой Regid (например: ru.myisp) вам на email (указанный в lirportal) придет письмо содержащие отчет об использовании вами вашего адресного пространства.
Объекты в БД
БД состоит из многих объектов, мы рассмотрим некоторые из них. Для примера возьмем хорошего магистрального провайдера: Транстелеком.
Объект person [описание полей объекта]
Это описание человека. Пример:
Видео пример создания объекта: смотреть
Видео пример проверки объекта: смотреть
Похож на объект « person «, но предназначен для описания не только контактного лица, но и роли, которое оно выполняет. Кроме того, объект « role » позволяет объединить несколько персон, выполняющих общую функцию (например отдел тех. поддержки, системных администраторов и т.д.). Для задания административных и технических контактов рекомендуется по возможности применять именно объект « role «. Пример:
Одноименные поля, заполняются так же, как и в объекте « person «. Обратите внимание, что в отличие от объекта « person » поле « e-mail » здесь является обязательным.
В поле « role » указывается название службы, к которой относится объект.
В полях « admin-c » и « tech-c » указываются nic-handle персон, отвечающих за административные и за технические вопросы. Таких полей может быть несколько.
Этот объект описывает ASSIGNMENT блок (блоки, подсети) адресов. Пример:
Этот объект указывает на то, какой автономной системе принадлежит сеть. Пример:
Этот объект описывает автономную систему. Пример:
В нем описывают не только кому принадлежит данный номер, административные и технические контакты,
но и описание пиров (peer) данной автономной системы и комьюнити (communities) которые можно
использовать.
Пиры:
…………[skiped]………………..
import: from AS174 action pref=120; accept AS174:AS-COGENT;
import: from AS786 action pref=120; accept AS-JANETPLUS;
import: from AS1290 action pref=120; accept AS-PSINETUK;
import: from AS2110 action pref=120; accept AS-IEUNET;
import: from AS2119 action pref=120; accept AS-TELENOR;
import: from AS2529 action pref=120; accept AS-DEMON;
…………[skiped]………………..
Составив комьюнити, исходя из описания, и, огласив его вместе с исходящим от вас маршрутом(ами), автономная система пира (в данном примере AS20485) выполнит те или иные действия: выполнит prepend (препенд — когда в as-path подставляется N раз ваш номер AS, что увеличивает as-path и соответственно ухудшает маршрут) или вовсе «запретит» (не будет анонсировать своим соседям) этот маршрут (префикс).
Это может позволит вам балансировать входящий трафик на ваших внешних каналах.
Данный объект используется для настройки входящих BGP фильтров, используются или префиксы или as-path. Пример:
Этот объект отвечает за DNS сервера. Благодаря ему можно указать DNS сервера отвечающие за обратный резолв (PTR записи) для вашего блока адресов. Пример:
Это необходимо если вы хотите, чтобы на команду nslookup ВАШ-IP-АДРЕС, вы и остальной мир, получали имя.
Пример: nslookup 217.150.32.1
1.32.150.217.in-addr.arpa name = ttk-eth1.transtk.ru.
Произносится как maintainer.
Строка auth и содержит зашифрованный пароль. Пароль криптуется как и в ОС FreeBSD ( /etc/master.passwd ), поэтому при создании объекта mntner свой пароль можно скопировать из файла /etc/master.passwd лиюо воспользоваться утилитой Crypted password generation на сайте RIPE.
Видео пример создания объекта: смотреть
Обязательно защищайте свои объекты с помощью mntner (поле « mnt-by «). Посмотрите видео пример как это сделать: смотреть
Надеюсь, что хоть немного стало понятней, т.к. по себе знаю, что с нуля врубаться в это дело сложновато.
Если у вас уже есть номер атономной системы и свой блок адресов, то пора внести в БД недостающие части. Вносить изменения в можно двумя способами:
На вашем месте я бы сначала пользовался 2-ым способом, т.к. там есть подсказки при создании объектов.
В поле « netname :» вписываем название для своей сети так же указанную в Address Plan.
В поле « status :» пишем ASSIGNED PA
Что писать в поле « mnt-by :» вы уже знаете 😉
Все остальные объекты создаются/редактируются по тому же принципу.
В объекте domain добавте столько полей « nserver :» сколько вам необходимо. В них нужно указать DNS имена ваших DNS серверов которые будут отвечать за reverse delegation (обратный просмотр(резолв)) ваших адресов. В « zone-c :» указываем nic-hdl человека который в вашей организации будет отвечать за зоны обраного просмотра.
Важно: если вы отредактировали свой as-set (добавили/удалили что-то), то вам необходимо сообщить об этом вашим peer`ам (соседям), т.к. не у всех есть автоматический апдейт фильтров.
Отредактируйте (если это необходимо) свой объект aut-num например добавив поле(я) « remarks :» или « descr :» с более подробным описанием своей сети или юр.лица которому она принадлежит, а так же, возможно, обновив свой « import :» или « export :» лист.
Таким образом мы сделали все, что необходимо для запуска своей AS с собственным блоком адресов.
Помним, что полное описание полей объекта можно получить выполнив в БД с ключем -v и именем объекта который нас интересует: пример.
Поля, отмеченные как [mandatory] являются обязательными для заполнения, должны обязательно присутствовать в заявке.
Поля, отмеченные как [single] могут присутствовать в заявке только в единственном экземпляре.
Поля, отмеченные как [multiple] могут присутствовать в нескольких экземплярах (например для указания нескольких телефонных номеров).
Поле « source » должно содержать значение «RIPE».
Поле « mnt-by » применяется для выбора способа авторизации дальнейших изменений в создаваемом объекте (см. объект « mntner «).
Удаление из БД делается точно так же как и создание. Единственное отличие, то что в конце добавляется поле « delete: » в котором вы и указываете причину удаления этого объекта.
Пока это все что я хотел вам поведать, комментарии/замечания приветствуются.
Полезные ссылки:
З.Ы.Ы. Мы можем оказать вам содействие в получении статуса LIR, номера автономной системы и собственного блока адресов для Вашей организации на возмездной основе.
Учебник Express часть 4: Маршруты и контроллеры
В этом уроке мы настроим маршруты (код обработки URL) с «фиктивными» функциями-обработчиками для всех конечных точек ресурса, которые нам понадобятся на веб-сайте LocalLibrary. По завершении мы получим модульную структуру для нашего кода обработки маршрута, который будет расширен реальными функциями-обработчиками в следующих статьях. У нас также будет хорошее понимание того, как создавать модульные маршруты с помощью Express!
Обзор
В последней статье мы определили модели Mongoose для взаимодействия с базой данных, и использовали (автономный) скрипт, который создал некоторые исходные записи библиотеки. Теперь можно написать код, чтобы представить эту информацию пользователям. Первое, что нужно сделать, это решить, какие возможности для отображения информации мы хотим иметь на наших страницах, а затем определить соответствующие URL-адреса для получения этих ресурсов. Затем нужно будет создать маршруты (обработчики URL-адресов) и представления (шаблоны) для отображения этих страниц.
Поскольку модели уже созданы, основные элементы, которые следует создать, таковы:
В первом разделе ниже приведён краткие основы того, как использовать промежуточное средство (middleware) Express Router. Эти знания будут использованы в следующих разделах при настройке маршрутов для LocalLibrary.
Есть несколько способов создания маршрутов. В этом уроке мы используем промежуточные запросы express.Router, так как они позволяют группировать обработчики маршрутов для определённой части сайта и получать к ним доступ через общий префикс маршрута. Все маршруты, связанные с библиотекой, будут сохранены в модуле «catalog», и если мы добавим маршруты для обработки учётных записей пользователей или других функций, мы сможем сгруппировать их отдельно.
В оставшейся части этого раздела представлен обзор того, как Router может быть использован для определения маршрутов.
Определение и использование отдельных модулей маршрутов
Код ниже является реальным примером того, как можно создать модуль маршрута, а затем использовать его в приложении Express.
Примечание: В примере колбэк-функции обработчиков маршрутов определены непосредственно в функциях роутеров. А в LocalLibrary мы определим эти колбэк-функции в отдельном модуле контроллера.
Чтобы использовать модуль роутера в главном приложении, прежде всего следует выполнить require() модуля маршрута (wiki.js). Потом вызовем use() для приложения Express с аргументом, в котором указан URL-путь ‘wiki’, что добавит Router к пути обработки промежуточного слоя.
Функции Route
HTTP глаголы (действия)
Рассмотренный пример использует метод Router.get() для ответа на HTTP GET- запросы с указанным путём.
Например, код ниже делает то же, что и предыдущий, с путём /about, но отвечает на HTTP POST-запросы.
Маршруты путей
Маршруты путей определяют конечные точки, в которых могут быть сделаны запросы. В уже рассмотренных примерах это были просто строки, которые использовались точно так, как были записаны: ‘/’, ‘/about’, ‘/book’, ‘/any-random.path’.
Примечание: Большинство наших маршрутов для библиотеки будут просто строками, а не образцами строк или регулярными выражениями. Кроме того, будут использоваться параметры маршрутов, что обсуждается в следующем разделе.
Параметры маршрутов
Имена параметров пути должны состоять из “символов слова” (A-Z, a-z, 0-9, и _).
Маршруты, необходимые для библиотеки LocalLibrary
Первая домашняя страница и страницы со списками не кодируют никакой дополнительной информации. Хотя результаты, возвращаемые запросами, будут зависеть от типа модели и от содержимого БД, запросы для получения этой информации всегда будут одинаковы (подобно тому, как код для создания объектов всегда будет одним и тем же).
В противоположность этому, другие URL используются для работы с определёнными экземплярами документов и моделей— индивидуальность элементов кодируется в URL (как выше). Параметры путей используются для извлечения информации и передачи её в обработчик пути (и в следующей статье мы применим этот приём для того, чтобы динамически определять, какую информацию следует получить из БД). By encoding the information in our URL we only need one route for every resource of a particular type (e.g. one route to handle the display of every single book item).
Далее мы создадим колбэк-функции обработчиков маршрутов и код маршрутов для всех указанных выше URL.
Создаём колбэк-функции обработчиков маршрутов
Начнём с создания каталога для контроллеров в корне проекта (/controllers), а затем создадим отдельные файлы (модули) контроллеров для работы с моделями:
Контроллер автора
Скопируем следующий код в файл /controllers/authorController.js:
BookInstance controller
Скопируйте следующий код в файл /controllers/bookinstanceController.js (он построен по образцу модуля контроллера для автора Author ):
Контроллер жанра
Скопируйте следующий код в файл /controllers/genreController.js (он построен по образцу модулей контроллеров для автора Author и экземпляра книги BookInstance ):
Контроллер книги
Скопируйте следующий код в файл /controllers/bookController.js. Он построен по образцу других модулей контроллеров, но ещё содержит функцию index() для вывода странички с приветствием:
Создание модуля для маршрута catalog
Далее мы создадим маршруты для всех URL, необходимых веб-сайту LocalLibrary, которые будут вызывать функции контроллеров, определённые в предыдущем разделе.
Каркас приложения уже содержит каталог ./routes, в котором есть маршруты для index и users. Внутри этого каталога создадим ещё один файл маршрутов — catalog.js ( см. ниже).
Скопируйте приведённый ниже код в файл /routes/catalog.js :
Все функции-обработчики импортируются из созданных в предыдущем разделе модулей контроллеров.
Обновление модуля маршрута index
Все новые маршруты заданы, а маршрут на начальную страницу остался без изменения. Давайте перенаправим его на новую страницу «index», которая создана в каталоге ‘/catalog’.
Откройте /routes/index.js и замените существующий маршрут приведённую ниже.
Обновление app.js
Откройте файл app.js и поместите require для маршрута каталог ниже других маршрутов (добавьте третью строку. показанную ниже, после имеющихся двух строк):
Далее, добавьте маршрут каталога в стек промежуточного слоя после других маршрутов (добавить третью строку после имеющихся двух):
Вот так. Теперь у нас есть пути и фиктивные функции, подготовленные для всех URL, которые мы собираемся поддерживать на веб-сайте LocalLibrary.
Проверка маршрутов
Чтобы проверить маршруты, сначала запустим веб-сайт обычным способом
После запуска перейдите к совокупности URL нашей LocalLibrary, и проверьте, что не появляется страница ошибки (HTTP 404). Небольшая часть наших URL для удобства приводится ниже:
Созданы все маршруты для нашего сайта. Созданы также фиктивные функции контроллеров, которые мы полностью реализуем в последующих статьях. Попутно мы изучили массу базовых сведений о маршрутах Express, и ознакомились с некоторыми подходами по структурированию маршрутов и контроллеров.
В следующей статье мы создадим настоящую страничку приветствия нашего сайта, для чего используем представления (шаблоны) и данные, хранящиеся в наших моделях.
Routed Events Overview
This topic describes the concept of routed events in Windows Presentation Foundation (WPF). The topic defines routed events terminology, describes how routed events are routed through a tree of elements, summarizes how you handle routed events, and introduces how to create your own custom routed events.
Prerequisites
This topic assumes that you have basic knowledge of the common language runtime (CLR) and object-oriented programming, as well as the concept of how the relationships between WPF elements can be conceptualized as a tree. In order to follow the examples in this topic, you should also understand Extensible Application Markup Language (XAML) and know how to write very basic WPF applications or pages. For more information, see Walkthrough: My first WPF desktop application and XAML in WPF.
What Is a Routed Event?
You can think about routed events either from a functional or implementation perspective. Both definitions are presented here, because some people find one or the other definition more useful.
Functional definition: A routed event is a type of event that can invoke handlers on multiple listeners in an element tree, rather than just on the object that raised the event.
Implementation definition: A routed event is a CLR event that is backed by an instance of the RoutedEvent class and is processed by the Windows Presentation Foundation (WPF) event system.
A typical WPF application contains many elements. Whether created in code or declared in XAML, these elements exist in an element tree relationship to each other. The event route can travel in one of two directions depending on the event definition, but generally the route travels from the source element and then «bubbles» upward through the element tree until it reaches the element tree root (typically a page or a window). This bubbling concept might be familiar to you if you have worked with the DHTML object model previously.
Consider the following simple element tree:
This element tree produces something like the following:
In this simplified element tree, the source of a Click event is one of the Button elements, and whichever Button was clicked is the first element that has the opportunity to handle the event. But if no handler attached to the Button acts on the event, then the event will bubble upwards to the Button parent in the element tree, which is the StackPanel. Potentially, the event bubbles to Border, and then beyond to the page root of the element tree (not shown).
In other words, the event route for this Click event is:
Top-level Scenarios for Routed Events
The following is a brief summary of the scenarios that motivated the routed event concept, and why a typical CLR event was not adequate for these scenarios:
Control composition and encapsulation: Various controls in WPF have a rich content model. For example, you can place an image inside of a Button, which effectively extends the visual tree of the button. However, the added image must not break the hit-testing behavior that causes a button to respond to a Click of its content, even if the user clicks on pixels that are technically part of the image.
Singular handler attachment points: In Windows Forms, you would have to attach the same handler multiple times to process events that could be raised from multiple elements. Routed events enable you to attach that handler only once, as was shown in the previous example, and use handler logic to determine where the event came from if necessary. For instance, this might be the handler for the previously shown XAML:
Class handling: Routed events permit a static handler that is defined by the class. This class handler has the opportunity to handle an event before any attached instance handlers can.
Referencing an event without reflection: Certain code and markup techniques require a way to identify a specific event. A routed event creates a RoutedEvent field as an identifier, which provides a robust event identification technique that does not require static or run-time reflection.
How Routed Events Are Implemented
A routed event is a CLR event that is backed by an instance of the RoutedEvent class and registered with the WPF event system. The RoutedEvent instance obtained from registration is typically retained as a public static readonly field member of the class that registers and thus «owns» the routed event. The connection to the identically named CLR event (which is sometimes termed the «wrapper» event) is accomplished by overriding the add and remove implementations for the CLR event. Ordinarily, the add and remove are left as an implicit default that uses the appropriate language-specific event syntax for adding and removing handlers of that event. The routed event backing and connection mechanism is conceptually similar to how a dependency property is a CLR property that is backed by the DependencyProperty class and registered with the WPF property system.
The following example shows the declaration for a custom Tap routed event, including the registration and exposure of the RoutedEvent identifier field and the add and remove implementations for the Tap CLR event.
Routed Event Handlers and XAML
To add a handler for an event using XAML, you declare the event name as an attribute on the element that is an event listener. The value of the attribute is the name of your implemented handler method, which must exist in the partial class of the code-behind file.
The XAML syntax for adding standard CLR event handlers is the same for adding routed event handlers, because you are really adding handlers to the CLR event wrapper, which has a routed event implementation underneath. For more information about adding event handlers in XAML, see XAML in WPF.
Routing Strategies
Routed events use one of three routing strategies:
Bubbling: Event handlers on the event source are invoked. The routed event then routes to successive parent elements until reaching the element tree root. Most routed events use the bubbling routing strategy. Bubbling routed events are generally used to report input or state changes from distinct controls or other UI elements.
Direct: Only the source element itself is given the opportunity to invoke handlers in response. This is analogous to the «routing» that Windows Forms uses for events. However, unlike a standard CLR event, direct routed events support class handling (class handling is explained in an upcoming section) and can be used by EventSetter and EventTrigger.
Tunneling: Initially, event handlers at the element tree root are invoked. The routed event then travels a route through successive child elements along the route, towards the node element that is the routed event source (the element that raised the routed event). Tunneling routed events are often used or handled as part of the compositing for a control, such that events from composite parts can be deliberately suppressed or replaced by events that are specific to the complete control. Input events provided in WPF often come implemented as a tunneling/bubbling pair. Tunneling events are also sometimes referred to as Preview events, because of a naming convention that is used for the pairs.
Why Use Routed Events?
As an application developer, you do not always need to know or care that the event you are handling is implemented as a routed event. Routed events have special behavior, but that behavior is largely invisible if you are handling an event on the element where it is raised.
Where routed events become powerful is if you use any of the suggested scenarios: defining common handlers at a common root, compositing your own control, or defining your own custom control class.
Routed event listeners and routed event sources do not need to share a common event in their hierarchy. Any UIElement or ContentElement can be an event listener for any routed event. Therefore, you can use the full set of routed events available throughout the working API set as a conceptual «interface» whereby disparate elements in the application can exchange event information. This «interface» concept for routed events is particularly applicable for input events.
Routed events can also be used to communicate through the element tree, because the event data for the event is perpetuated to each element in the route. One element could change something in the event data, and that change would be available to the next element in the route.
Other than the routing aspect, there are two other reasons that any given WPF event might be implemented as a routed event instead of a standard CLR event. If you are implementing your own events, you might also consider these principles:
Certain WPF styling and templating features such as EventSetter and EventTrigger require the referenced event to be a routed event. This is the event identifier scenario mentioned earlier.
Routed events support a class handling mechanism whereby the class can specify static methods that have the opportunity to handle routed events before any registered instance handlers can access them. This is very useful in control design, because your class can enforce event-driven class behaviors that cannot be accidentally suppressed by handling an event on an instance.
Each of the above considerations is discussed in a separate section of this topic.
Adding and Implementing an Event Handler for a Routed Event
To add an event handler in XAML, you simply add the event name to an element as an attribute and set the attribute value as the name of the event handler that implements an appropriate delegate, as in the following example.
b1SetColor is the name of the implemented handler that contains the code that handles the Click event. b1SetColor must have the same signature as the RoutedEventHandler delegate, which is the event handler delegate for the Click event. The first parameter of all routed event handler delegates specifies the element to which the event handler is added, and the second parameter specifies the data for the event.
RoutedEventHandler is the basic routed event handler delegate. For routed events that are specialized for certain controls or scenarios, the delegates to use for the routed event handlers also might become more specialized, so that they can transmit specialized event data. For instance, in a common input scenario, you might handle a DragEnter routed event. Your handler should implement the DragEventHandler delegate. By using the most specific delegate, you can process the DragEventArgs in the handler and read the Data property, which contains the clipboard payload of the drag operation.
For a complete example of how to add an event handler to an element using XAML, see Handle a Routed Event.
The next example shows the C# operator syntax (Visual Basic has slightly different operator syntax because of its handling of dereferencing):
For an example of how to add an event handler in code, see Add an Event Handler Using Code.
If you are using Visual Basic, you can also use the Handles keyword to add handlers as part of the handler declarations. For more information, see Visual Basic and WPF Event Handling.
The Concept of Handled
However, there is a «handledEventsToo» mechanism whereby listeners can still run handlers in response to routed events where Handled is true in the event data. In other words, the event route is not truly stopped by marking the event data as handled. You can only use the handledEventsToo mechanism in code, or in an EventSetter:
In addition to the behavior that Handled state produces in routed events, the concept of Handled has implications for how you should design your application and write the event handler code. You can conceptualize Handled as being a simple protocol that is exposed by routed events. Exactly how you use this protocol is up to you, but the conceptual design for how the value of Handled is intended to be used is as follows:
If a routed event is marked as handled, then it does not need to be handled again by other elements along that route.
Take no action at all; the event remains unhandled, and the event routes to the next listener.
Execute code in response to the event, but make the determination that the action taken was not substantial enough to warrant marking the event as handled. The event routes to the next listener.
Execute code in response to the event. Mark the event as handled in the event data passed to the handler, because the action taken was deemed substantial enough to warrant marking as handled. The event still routes to the next listener, but with Handled= true in its event data, so only handledEventsToo listeners have the opportunity to invoke further handlers.
For more information about Handled, class handling of routed events, and recommendations about when it is appropriate to mark a routed event as Handled, see Marking Routed Events as Handled, and Class Handling.
In applications, it is quite common to just handle a bubbling routed event on the object that raised it, and not be concerned with the event’s routing characteristics at all. However, it is still a good practice to mark the routed event as handled in the event data, to prevent unanticipated side effects just in case an element that is further up the element tree also has a handler attached for that same routed event.
Class Handlers
If you are defining a class that derives in some way from DependencyObject, you can also define and attach a class handler for a routed event that is a declared or inherited event member of your class. Class handlers are invoked before any instance listener handlers that are attached to an instance of that class, whenever a routed event reaches an element instance in its route.
Some WPF controls have inherent class handling for certain routed events. This might give the outward appearance that the routed event is not ever raised, but in reality it is being class handled, and the routed event can potentially still be handled by your instance handlers if you use certain techniques. Also, many base classes and controls expose virtual methods that can be used to override class handling behavior. For more information both on how to work around undesired class handling and on defining your own class handling in a custom class, see Marking Routed Events as Handled, and Class Handling.
Attached Events in WPF
The XAML language also defines a special type of event called an attached event. An attached event enables you to add a handler for a particular event to an arbitrary element. The element handling the event need not define or inherit the attached event, and neither the object potentially raising the event nor the destination handling instance must define or otherwise «own» that event as a class member.
The WPF input system uses attached events extensively. However, nearly all of these attached events are forwarded through base elements. The input events then appear as equivalent non-attached routed events that are members of the base element class. For instance, the underlying attached event Mouse.MouseDown can more easily be handled on any given UIElement by using MouseDown on that UIElement rather than dealing with attached event syntax either in XAML or code.
For more information about attached events in WPF, see Attached Events Overview.
Qualified Event Names in XAML
Another syntax usage that resembles typename.eventname attached event syntax but is not strictly speaking an attached event usage is when you attach handlers for routed events that are raised by child elements. You attach the handlers to a common parent, to take advantage of event routing, even though the common parent might not have the relevant routed event as a member. Consider this example again:
Here, the parent element listener where the handler is added is a StackPanel. However, it is adding a handler for a routed event that was declared and will be raised by the Button class (ButtonBase actually, but available to Button through inheritance). Button «owns» the event, but the routed event system permits handlers for any routed event to be attached to any UIElement or ContentElement instance listener that could otherwise attach listeners for a common language runtime (CLR) event. The default xmlns namespace for these qualified event attribute names is typically the default WPF xmlns namespace, but you can also specify prefixed namespaces for custom routed events. For more information about xmlns, see XAML Namespaces and Namespace Mapping for WPF XAML.
WPF Input Events
One frequent application of routed events within the WPF platform is for input events. In WPF, tunneling routed events names are prefixed with the word «Preview» by convention. Input events often come in pairs, with one being the bubbling event and the other being the tunneling event. For example, the KeyDown event and the PreviewKeyDown event have the same signature, with the former being the bubbling input event and the latter being the tunneling input event. Occasionally, input events only have a bubbling version, or perhaps only a direct routed version. In the documentation, routed event topics cross-reference similar routed events with alternative routing strategies if such routed events exist, and sections in the managed reference pages clarify the routing strategy of each routed event.
WPF input events that come in pairs are implemented so that a single user action from input, such as a mouse button press, will raise both routed events of the pair in sequence. First, the tunneling event is raised and travels its route. Then the bubbling event is raised and travels its route. The two events literally share the same event data instance, because the RaiseEvent method call in the implementing class that raises the bubbling event listens for the event data from the tunneling event and reuses it in the new raised event. Listeners with handlers for the tunneling event have the first opportunity to mark the routed event handled (class handlers first, then instance handlers). If an element along the tunneling route marked the routed event as handled, the already-handled event data is sent on for the bubbling event, and typical handlers attached for the equivalent bubbling input events will not be invoked. To outward appearances it will be as if the handled bubbling event has not even been raised. This handling behavior is useful for control compositing, where you might want all hit-test based input events or focus-based input events to be reported by your final control, rather than its composite parts. The final control element is closer to the root in the compositing, and therefore has the opportunity to class handle the tunneling event first and perhaps to «replace» that routed event with a more control-specific event, as part of the code that backs the control class.
As an illustration of how input event processing works, consider the following input event example. In the following tree illustration, leaf element #2 is the source of both a PreviewMouseDown and then a MouseDown event:
The order of event processing is as follows:
PreviewMouseDown (tunnel) on root element.
PreviewMouseDown (tunnel) on intermediate element #1.
PreviewMouseDown (tunnel) on source element #2.
MouseDown (bubble) on source element #2.
MouseDown (bubble) on intermediate element #1.
MouseDown (bubble) on root element.
A routed event handler delegate provides references to two objects: the object that raised the event and the object where the handler was invoked. The object where the handler was invoked is the object reported by the sender parameter. The object where the event was first raised is reported by the Source property in the event data. A routed event can still be raised and handled by the same object, in which case sender and Source are identical (this is the case with Steps 3 and 4 in the event processing example list).
Because of tunneling and bubbling, parent elements receive input events where the Source is one of their child elements. When it is important to know what the source element is, you can identify the source element by accessing the Source property.
Usually, once the input event is marked Handled, further handlers are not invoked. Typically, you should mark input events as handled as soon as a handler is invoked that addresses your application-specific logical handling of the meaning of the input event.
The exception to this general statement about Handled state is that input event handlers that are registered to deliberately ignore Handled state of the event data would still be invoked along either route. For more information, see Preview Events or Marking Routed Events as Handled, and Class Handling.
The shared event data model between tunneling and bubbling events, and the sequential raising of first tunneling then bubbling events, is not a concept that is generally true for all routed events. That behavior is specifically implemented by how WPF input devices choose to raise and connect the input event pairs. Implementing your own input events is an advanced scenario, but you might choose to follow that model for your own input events also.
Certain classes choose to class-handle certain input events, usually with the intent of redefining what a particular user-driven input event means within that control and raising a new event. For more information, see Marking Routed Events as Handled, and Class Handling.
For more information on input and how input and events interact in typical application scenarios, see Input Overview.
EventSetters and EventTriggers
In styles, you can include some pre-declared XAML event handling syntax in the markup by using an EventSetter. When the style is applied, the referenced handler is added to the styled instance. You can declare an EventSetter only for a routed event. The following is an example. Note that the b1SetColor method referenced here is in a code-behind file.
The advantage gained here is that the style is likely to contain a great deal of other information that could apply to any button in your application, and having the EventSetter be part of that style promotes code reuse even at the markup level. Also, an EventSetter abstracts method names for handlers one step further away from the general application and page markup.
Another specialized syntax that combines the routed event and animation features of WPF is an EventTrigger. As with EventSetter, only routed events may be used for an EventTrigger. Typically, an EventTrigger is declared as part of a style, but an EventTrigger can also be declared on page-level elements as part of the Triggers collection, or in a ControlTemplate. An EventTrigger enables you to specify a Storyboard that runs whenever a routed event reaches an element in its route that declares an EventTrigger for that event. The advantage of an EventTrigger over just handling the event and causing it to start an existing storyboard is that an EventTrigger provides better control over the storyboard and its run-time behavior. For more information, see Use Event Triggers to Control a Storyboard After It Starts.
More About Routed Events
This topic mainly discusses routed events from the perspective of describing the basic concepts and offering guidance on how and when to respond to the routed events that are already present in the various base elements and controls. However, you can create your own routed event on your custom class along with all the necessary support, such as specialized event data classes and delegates. The routed event owner can be any class, but routed events must be raised by and handled by UIElement or ContentElement derived classes in order to be useful. For more information about custom events, see Create a Custom Routed Event.