Perché non questo gestore classe attaccato ad un evento fuoco tunnel prima di un gestore di esempio?

StackOverflow https://stackoverflow.com/questions/9320916

Domanda

questo MSDN articolo (tra gli altri),

gestori di classe vengono richiamati prima di eventuali gestori esempio ascoltatore che sono allegati a un'istanza di tale classe, ogni volta che un evento indirizzato raggiunge un'istanza elemento nel suo percorso.

Sono abbastanza nuovo per RoutedEvents quindi c'è una possibilità che ho un errore nel mio codice, ma sembra come se un gestore di classe attaccato ad un RoutedEvent che viene dichiarato come RoutingStrategy.Tunnel non sempre il fuoco prima che i gestori di grado, che affianca lo stesso evento.

Nel mio esempio qui sotto, ho creato una classe di controllo TouchButton con un RoutedEvent tunneling e RoutedEvent bubbling. Mi sono registrato i gestori di classe per ciascuno. Poi ho creato un'istanza della classe in una finestra e gestire ogni evento nel codice dietro. Ho attaccato lo stesso gestore per l'evento tunneling sia l'elemento di classe e la Grid che lo contiene. Tutti e quattro i gestori di mostrare il loro nome in un MessageBox in modo da poter vedere chiaramente l'ordine di esecuzione.

  1. Griglia grado PreviewTouch
  2. Classe TouchButton_PreviewTouch
  3. TouchButton grado PreviewTouch
  4. Classe TouchButton_Touch
  5. TouchButton istanza tocco

Questo significa che se chiamo e.Handled = true; nel gestore eventi classe PreviewTouch, posso interrompere l'esecuzione di raggiungere tutti gli altri gestori di eventi tranne quella adiacente all'elemento Grid. È questo dovrebbe essere così, o ti ho fatto un qualche errore? In caso contrario, come posso interrompere l'esecuzione di raggiungere tutti istanza del gestore di eventi?

Questa è la classe:

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));
    }
}

Ecco i gestori di istanza nel codice finestra dietro:

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));
}

Ecco l'XAML di controllo:

<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>

Capisco che l'evento tunneling viene gestito dall'elemento Grid prima di 'tunneling' verso il basso per l'elemento TouchButton, ma ho pensato che i gestori di classe sono stati sempre tenuti a fuoco prima che i gestori di istanza. Se no, come posso raggiungere questo obiettivo?

UPDATE >>>

Grazie a @ di sanguine risposta, sono riuscito a trovare un modo per fermare tutti i gestori di istanza dalla gestione dell'evento. Se invece di sostituire il tipo di trattamento effettuato con TouchButton Grid come suggerito sanguigna classe dichiarata, lo sostituisco con FrameworkElement, allora sarà catturare tutti i controlli FrameworkElement-derivato.

EventManager.RegisterClassHandler(typeof(FrameworkElement), PreviewTouchEvent, 
new RoutedEventHandler(TouchButton_PreviewTouch), true);
È stato utile?

Soluzione

MSDN: un articolo - Quando un evento di spostamento trova un elemento (nella struttura), che ha disposizione sia di handler di classe e l'istanza poi invoca gestore classe prima del gestore istanza. Quindi in questo caso, quando evento viene generato e tunnel da fuori a dentro, incontra griglia ma la classe griglia non ha alcun gestore di classe in modo che semplicemente chiama il gestore istanza utilizzata dall'istanza "Grid". Se si aggiunge questa linea nel pulsante di attivazione -

EventManager.RegisterClassHandler (typeof ( Griglia ), PreviewTouchEvent, nuova RoutedEventHandler (TouchButton_PreviewTouch), true);

di prima istanza del gestore di rete, sarà chiamato il gestore di classe corrispondente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top