2011-10-04 16 views
9

Me di cuenta de que cuando se usa una InvokeCommandAcction asociada a un EventTrigger, el evento original todavía enrutaba hasta los elementos principales hasta que se manejara. Bueno, supongo que es un comportamiento esperado. Pero mi pregunta es cómo puedo marcar el evento como Handled para que no se propague a través de todo el árbol de UI.¿Cómo evitar que InvokeCommandAction propague eventos a elementos principales?

En realidad, como maneja este evento en un comando, todo se manejará en este comando, por lo tanto, no necesita propagarse. Y en un caso de esquina que encontré, causa un comportamiento no deseado. Por ejemplo, abro una nueva ventana cuando un usuario hace doble clic en un elemento (evento MouseDoubleClick). El problema es que se abren las nuevas ventanas y luego la ventana principal vuelve al frente de la nueva porque el evento MouseDoubleClick acaba de llegar al elemento superior en el árbol de la interfaz de usuario. El comportamiento deseado sería mantener la nueva ventana al frente, pero como InvokeCommandAction permite que el evento se propague, la ventana principal recupera el foco ...

Lo que podría hacer es usar el elemento CallMethodAction en su lugar pero como Estoy en un escenario MVVM, no quiero argumentos de evento UI en mi código. Incluso si esto me permite marcar implícitamente el evento como manejado y solucionar el problema.

<UserControl x:Class="..." 
      xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="MouseDoubleClick"> 
      <i:InvokeCommandAction Command="{Binding Path=DisplayReportCommand}"/> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
    ... 
</UserControl> 

Respuesta

17

Puede implementar su propio EventTrigger que marque eventos como manejados.

public class HandlingEventTrigger : System.Windows.Interactivity.EventTrigger 
{ 
    protected override void OnEvent(System.EventArgs eventArgs) 
    { 
     var routedEventArgs = eventArgs as RoutedEventArgs; 
     if (routedEventArgs != null) 
      routedEventArgs.Handled = true; 

     base.OnEvent(eventArgs); 
    } 
} 

A continuación, reemplace <i:EventTrigger EventName="MouseDoubleClick"> con <local:HandlingEventTrigger EventName="MouseDoubleClick"> y añadir

xmlns:local="clr-namespace:HandlingEventTrigger's namespace here" 

a los atributos de su UserControl.

+0

Esto parece ser una muy buena idea. Esperaré por más respuestas. Gracias. – Ucodia

+1

Escogí esta respuesta porque es la solución más limpia que puedo usar en un escenario de MVVM. – Ucodia

+1

Para Windows Phone, en lugar de RoutedEventArgs usa GestureEventArgs. –

1

Agregar evento adjunto al control de usuario

   CommandManager.PreviewCanExecute="PreviewCanExecute" 

y en el controlador de eventos

   e.ContinueRouting = false; 

Hope esto help!

+0

Ok gracias. Voy a probar esto. – Ucodia

0

MouseDoubleClick Event no es en realidad un evento de enrutamiento burbujeante sino un evento enrutado directo.

Sin embargo, este evento se plantea a lo largo del árbol de elementos, que se puede comprobar con la herramienta Snoop. Además, incluso si Handled for MouseDoubleClick está establecido en verdadero, este evento ocurrirá a lo largo del árbol de elementos.

Aunque este evento enrutado (MouseDoubleClick Evento) parece seguir una ruta que burbujea a través de un árbol de elementos, que en realidad es un evento enrutado directo que se alza a lo largo del árbol de elementos por cada UIElement.

Si establece la propiedad Handled en true en un controlador de eventos MouseDoubleClick, los sucesos posteriores de MouseDoubleClick a lo largo de la ruta se producirán con Handled establecido en false. Este es un evento de nivel superior para consumidores de control que desean recibir notificaciones cuando el usuario hace doble clic en el control y maneja el evento en una aplicación. (De MSDN)

Como se mencionó anteriormente, su problema puede no ser causado por la propagación. Hay propiedad Window.ShowActivated, que determina si una ventana se activa cuando se muestra por primera vez.Puede establecer la propiedad en una ventana secundaria (xaml) como se muestra a continuación, pero tenga en cuenta que aunque ShowActivated puede centrar la ventana principal, no puede dejar que la ventana principal se mantenga visual al frente de la ventana secundaria. Intenté encontrar la solución, pero no tengo idea hasta ahora.

<Window ShowActivated="False" ....> 
.... 
</Window> 
Cuestiones relacionadas