2012-02-16 5 views
1

Согласно this MSDN article (среди прочих),Почему этот обработчик класса не подключен к событию туннелирования перед обработчиком экземпляра?

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

Я совершенно новый для RoutedEvent с так что есть шанс, что у меня есть ошибка в моем коде, но это, кажется, как будто обработчик класса привязанный к RoutedEvent, который объявлен как RoutingStrategy.Tunnel делает не всегда перед обработчиками экземпляров, прикрепленными к одному и тому же событию.

В моем примере ниже, я создал класс управления TouchButton с туннелированием RoutedEvent и пузырящийся RoutedEvent. Я зарегистрировал обработчики классов для каждого. Затем я создал экземпляр класса в окне и обрабатывал каждое событие в коде позади. Я применил тот же обработчик для события туннелирования как элемента класса, так и Grid, который содержит его. Все четыре обработчика отображают свое имя в MessageBox, чтобы вы могли четко видеть порядок выполнения.

  1. Сетка Instance PreviewTouch
  2. Класс TouchButton_PreviewTouch
  3. TouchButton Instance PreviewTouch
  4. Класс TouchButton_Touch
  5. 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); 
+0

Хороший вопрос ... – sanguine

ответ

0

MSDN статья означает - Когда событие перемещения находит элемент (в дереве), которое имеет обеспечение как класс и экземпляр обработчик, то он вызывает обработчик класса до обработчика экземпляра. Поэтому в этом случае, когда событие запускается и туннелируется извне, оно встречает сетку, но класс Grid не имеет обработчика класса, поэтому он просто вызывает обработчик экземпляра, используемый экземпляром «Grid». Если эта строка добавляется в переключателе кнопку-

EventManager.RegisterClassHandler (TypeOf (Сетки), PreviewTouchEvent, нового RoutedEventHandler (TouchButton_PreviewTouch), правда);

, то перед обработчиком экземпляра Grid будет вызываться соответствующий обработчик класса.

+0

Привет, сангвиник, спасибо за ваш ответ. Это не совсем отвечало на мой вопрос, но это помогло мне самому ответить на него, поэтому я дам вам это. :) – Sheridan