Согласно this MSDN article (среди прочих),Почему этот обработчик класса не подключен к событию туннелирования перед обработчиком экземпляра?
обработчиков класса вызываются до любого экземпляра обработчиков слушателя, что прикреплены к экземпляру этого класса, всякий раз, когда маршрутизация события достигает экземпляр элемента на своем пути.
Я совершенно новый для RoutedEvent
с так что есть шанс, что у меня есть ошибка в моем коде, но это, кажется, как будто обработчик класса привязанный к RoutedEvent
, который объявлен как RoutingStrategy.Tunnel
делает не всегда перед обработчиками экземпляров, прикрепленными к одному и тому же событию.
В моем примере ниже, я создал класс управления TouchButton
с туннелированием RoutedEvent
и пузырящийся RoutedEvent
. Я зарегистрировал обработчики классов для каждого. Затем я создал экземпляр класса в окне и обрабатывал каждое событие в коде позади. Я применил тот же обработчик для события туннелирования как элемента класса, так и Grid
, который содержит его. Все четыре обработчика отображают свое имя в MessageBox
, чтобы вы могли четко видеть порядок выполнения.
- Сетка Instance PreviewTouch
- Класс TouchButton_PreviewTouch
- TouchButton Instance PreviewTouch
- Класс TouchButton_Touch
- TouchButton Instance касания
Это означает, что, если я позвоню e.Handled = true;
в обработчик событий класса PreviewTouch
, Я могу остановить исполнение от достижения всех r, за исключением тех, которые прикреплены к элементу Grid
. Это должно быть так, или я где-то ошибся? В противном случае, как я могу остановить выполнение от достижения каждые обработчик события экземпляра?
Вот класс:
public class TouchButton : Button
{
static TouchButton()
{
EventManager.RegisterClassHandler(typeof(TouchButton), PreviewTouchEvent,
new RoutedEventHandler(TouchButton_PreviewTouch), true);
EventManager.RegisterClassHandler(typeof(TouchButton), TouchEvent,
new RoutedEventHandler(TouchButton_Touch), true);
}
private static void TouchButton_PreviewTouch(object sender, RoutedEventArgs e)
{
MessageBox.Show("Class TouchButton_PreviewTouch");
}
private static void TouchButton_Touch(object sender, RoutedEventArgs e)
{
MessageBox.Show("Class TouchButton_Touch");
}
public static RoutedEvent TouchEvent = EventManager.RegisterRoutedEvent("Touch",
RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TouchButton));
public event RoutedEventHandler Touch
{
add { AddHandler(TouchEvent, value); }
remove { RemoveHandler(TouchEvent, value); }
}
public static RoutedEvent PreviewTouchEvent = EventManager.RegisterRoutedEvent(
"PreviewTouch", RoutingStrategy.Tunnel, typeof(RoutedEventHandler),
typeof(TouchButton));
public event RoutedEventHandler PreviewTouch
{
add { AddHandler(PreviewTouchEvent, value); }
remove { RemoveHandler(PreviewTouchEvent, value); }
}
protected override void OnClick()
{
RaiseTouchEvent();
}
private void RaiseTouchEvent()
{
RoutedEventArgs touchEventArgs = new RoutedEventArgs(PreviewTouchEvent);
RaiseEvent(touchEventArgs);
if (!touchEventArgs.Handled) RaiseEvent(new RoutedEventArgs(TouchEvent));
}
}
Вот обработчики экземпляра в окне кода позади:
private void TouchButton_PreviewTouch(object sender, RoutedEventArgs e)
{
MessageBox.Show(string.Format("{0} Instance PreviewTouch",
((FrameworkElement)sender).Name));
}
private void TouchButton_Touch(object sender, RoutedEventArgs e)
{
MessageBox.Show(string.Format("{0} Instance Touch",
((FrameworkElement)sender).Name));
}
Здесь управление XAML:
<Grid Name="Grid" Controls:TouchButton.PreviewTouch="TouchButton_PreviewTouch">
<Controls:TouchButton x:Name="TouchButton" Width="200" Height="45" FontSize="24"
Content="Touch me" Touch="TouchButton_Touch" PreviewTouch="TouchButton_PreviewTouch" />
</Grid>
Я понимаю, что событие туннелирования обрабатывается элементом Grid
до «туннелирования» до TouchButton
, но я думал, что обработчики класса всегда должны были запускать перед обработчиками экземпляров. Если нет, как я могу это достичь?
UPDATE >>>
Благодаря @ ответ сангвиник, я сумел найти способ остановить все обработчики экземпляра от обработки события.Если вместо замены объявленного типа обработки класса TouchButton
на Grid
, как предложено sanguine, я заменяю его FrameworkElement
, после чего он поймает все элементы управления FrameworkElement
.
EventManager.RegisterClassHandler(typeof(FrameworkElement), PreviewTouchEvent,
new RoutedEventHandler(TouchButton_PreviewTouch), true);
Хороший вопрос ... – sanguine