2010-02-18 12 views
9

Tengo un UserControl que agrega un CommandBinding a su colección de CommandBindings para manejar un comando específico. Más tarde utilizo este control en una ventana y deseo agregar otro enlace a ese mismo control para agregar un comportamiento adicional. El problema, sin embargo, es que cuando hago esto parece que cuando agrego otro CommandBinding a la colección CommandBindings de un control que reemplaza cualquier enlace que ya estaba hecho para el mismo Comando. Así que lo que parece es que un control solo puede tener un único CommandBinding por control, ¿es correcto?¿Puedo tener múltiples Comandos de Comando para el mismo Comando en el mismo control?

Consulte el siguiente ejemplo de código que intenta establecer dos Combinaciones de comandos para el mismo comando Guardar.

<Window x:Class="MultipleCommandBindings.Window1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="Window1" Height="300" Width="300"> 
<Window.CommandBindings> 
    <CommandBinding Command="Save" 
        Executed="CommandBinding_Executed" /> 
    <CommandBinding Command="Save" 
        Executed="CommandBinding_Executed" /> 
</Window.CommandBindings> 
<Grid> 
    <Button Height="23" 
      HorizontalAlignment="Right" 
      Margin="0,0,25,88" 
      Name="button1" 
      VerticalAlignment="Bottom" 
      Width="75" 
      Command="Save">Button</Button> 
</Grid> 

Al principio yo estaba esperando ya sea un tiempo de compilación o excepción en tiempo de ejecución cuando se escribió este código, pero se sorprendió de que no se quejó. Luego, me decepcionó porque mi manejador CommandBinding_Executed solo es llamado una vez en lugar de dos veces como esperaba.

Actualización: Después de un poco de pruebas parece que mi segundo CommandBinding no es sobrescribir mi primera vez, pero parece que a pesar de que no estoy ajuste manejado a verdad en mi controlador de eventos que la unión del primer comando traga el Comando. Estoy bastante seguro en este punto de que la solución a mi problema es entender por qué el comando enrutado no se está propagando más allá del primer controlador, incluso cuando Handled no está configurado en verdadero.

Actualización: que he encontrado this great little tidbit de información que sólo confirma algunos de los comportamientos extraños detrás de comandos de enrutamiento en WPF.

Actualización: Un pensamiento sobre cómo solucionar el hecho de que parece que sólo puede haber un único CommandBinding efectivo por comando es que parece que la clase CommandBinding predeterminado expone ejecutado y CanExecute como eventos que por supuesto al igual que todos los eventos pueden tener múltiples controladores. La idea es tener un método diferente al método estándar CommandBindings.Add para agregar manejadores adicionales a un comando. Tal vez esto podría hacerse a través de un método de extensión en la clase Control y junto con una clase CompositeCommandBinding personalizada que nos permite agregar múltiples enlaces dentro de un enlace principal.

+0

La única solución que puedo pensar es suscribirme al evento Click de Button y luego convertir DataContext de View como su ViewModel y usar esa var para ejecutar 2 comandos manualmente. –

Respuesta

1

No sé la respuesta a su pregunta, pero el uso de Reflector me parece razonable.

Me pregunto por qué haces esto? ¿Tal vez tiene más sentido utilizar el patrón Composite para agregar comportamientos, en lugar de intentar combinar enlaces de comandos?

+1

+1 por la noción de que debe tener solo 1 enlace en la vista y permitir que se invoquen múltiples comportamientos más adelante en la pila. –

+0

Bueno, en mi caso tengo un Control de usuario que puede ser el origen de varios tipos diferentes de comandos que se propagan que provienen de un control interno. Dentro del control de usuario, quiero saber cuándo se emiten cualquiera de estos comandos para que mi ViewModel pueda iniciar otros procesos cuyo resultado final se expondrá a través de UserControl (View). Puedo enlazar a la propiedad que estoy exponiendo y ver cuándo cambió para saber cuándo está lista para usar, pero miro la información sobre el tipo de comando real que comenzó todo el proceso. – jpierson

3

Hasta ahora solo he podido encontrar una solución para este problema, que es manejar el comando en dos niveles diferentes en el árbol lógico. En el siguiente ejemplo, manejo el comando Guardar dentro de mi cuadrícula y luego también dentro del elemento Ventana.

<Window x:Class="MultipleCommandBindings.Window1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="Window1" Height="300" Width="300"> 
<Window.CommandBindings> 
    <CommandBinding Command="Save" 
        Executed="CommandBinding_Executed2"/> 
</Window.CommandBindings> 
<Grid> 
    <Grid.CommandBindings> 
     <CommandBinding Command="Save" 
         Executed="CommandBinding_Executed1" /> 
    </Grid.CommandBindings> 

    <Button Height="23" 
      HorizontalAlignment="Right" 
      Margin="0,0,25,88" 
      Name="button1" 
      VerticalAlignment="Bottom" 
      Width="75" 
      Command="Save">Button</Button> 
</Grid> 

Con el fin de conseguir que esto funcione mi código detrás también hay que propagar manualmente la ejecución de comandos para el siguiente nivel.

private void CommandBinding_Executed1(object sender, ExecutedRoutedEventArgs e) 
    { 
     System.Diagnostics.Debug.WriteLine("Executed 1!"); 
     var command = e.Command as RoutedUICommand; 
     command.Execute(e.Parameter, this); 
    } 

    private void CommandBinding_Executed2(object sender, ExecutedRoutedEventArgs e) 
    { 
     System.Diagnostics.Debug.WriteLine("Executed 2!"); 
    } 

todavía Si alguien tiene alguna idea mejor sobre cómo puedo controlar un comando de dejar que se propagan de forma natural en el árbol me gustaría ver que de lo contrario sólo podría recurrir a esta solución.

Cuestiones relacionadas