2012-04-12 8 views
48

Así que he estado buscando y no puedo encontrar exactamente cómo hacerlo. Estoy creando un control de usuario usando MVVM y me gustaría ejecutar un comando en el evento 'Cargado'. Me doy cuenta de que esto requiere un poco de código, pero no puedo entender qué se necesita. El comando se encuentra en ViewModel, que está configurado como el contexto de datos de la vista, pero no estoy seguro de cómo enrutarlo para poder llamarlo desde el código que se encuentra detrás del evento cargado. Básicamente lo que quiero es algo como esto ...Comando de llamada del código detrás

private void UserControl_Loaded(object sender, RoutedEventArgs e) 
{ 
    //Call command from viewmodel 
} 

Mirando alrededor me parece que no puede encontrar la sintaxis para esto en cualquier lugar. ¿Debo unir el comando en el xaml primero para poder hacer referencia a él? Puedo tener la opción de enlaces de comando dentro de un control de usuario no le permitirá enlazar comandos que puedas en algo así como un botón ...

<UserControl.CommandBindings> 
    <CommandBinding Command="{Binding MyCommand}" /> <!-- Throws compile error --> 
</UserControl.CommandBindings> 

Estoy seguro de que hay una forma sencilla de hacer esto, pero no puedo' t por la vida de mi entenderlo.

Respuesta

101

Bueno, si el DataContext ya está establecido que pudieras jugar y llamar al comando:

var viewModel = (MyViewModel)DataContext; 
if (viewModel.MyCommand.CanExecute(null)) 
    viewModel.MyCommand.Execute(null); 

(Cambio de parámetros según sea necesario)

+0

Sí, eso es exactamente lo que necesitaba, sabía que había una manera fácil. ¡Gracias! –

+0

@KDiTraglia: De nada, me alegro de que haya ayudado. –

+0

Debería comprobar si viewModel es nulo antes de intentar acceder MyCommand. Sé que mi solución no, pero es la respuesta aceptada, así que probablemente debería estar allí. – Alain

1

Prueba esto:

private void UserControl_Loaded(object sender, RoutedEventArgs e) 
{ 
    //Optional - first test if the DataContext is not a MyViewModel 
    if(!this.DataContext is MyViewModel) return; 
    //Optional - check the CanExecute 
    if(!((MyViewModel) this.DataContext).MyCommand.CanExecute(null)) return; 
    //Execute the command 
    ((MyViewModel) this.DataContext).MyCommand.Execute(null) 
} 
+2

No debe llamar a un comando sin asegurarse de que se puede ejecutar primero. –

+0

Si solo está utilizando CanExecute para determinar si el usuario puede ejecutarlo (es decir, enlazar al estado habilitado de un botón) no tiene nada de malo. – Alain

+3

Con un botón, el control garantiza que el comando nunca se ejecute sin cuidado, si lo ejecuta manualmente, tendrá que encargarse de eso usted mismo. –

3

Prefacio: sin saber más acerca de sus requisitos, parece que el código huele a ejecutar un comando desde el código subyacente al momento de la carga. Tiene que haber una forma mejor, MVVM.

Pero, si realmente es necesario hacerlo en código detrás, algo como esto sería probablemente el trabajo (nota: no se puede probar esto por el momento):

private void UserControl_Loaded(object sender, RoutedEventArgs e)  
{ 
    // Get the viewmodel from the DataContext 
    MyViewModel vm = this.DataContext as MyViewModel; 

    //Call command from viewmodel  
    if ((vm != null) && (vm.MyCommand.CanExecute(null))) 
     vm.MyCommand.Execute(null); 
} 

Una vez más - tratar de encontrar una manera mejor ...

+1

Al buscar el tema, realmente no hay una manera fácil, y el consenso general que he visto es un pequeño código que nunca mató a nadie. –

+1

@KDiTraglia - cierto, pero en general, el "pequeño código detrás" generalmente se refiere a las acciones que afectan solo a la Vista en sí (es decir, cosas como seleccionar todo el texto en un cuadro de texto cuando se enfoca). Aquí, interactúa directamente con ViewModel desde el código subyacente de View, que rompe el principio de MVVM. –

1

Tengo una solución más compacta que quiero compartir. Debido a que a menudo ejecuto comandos en mi ViewModels, me cansé de escribir la misma instrucción if. Así que escribí una extensión para la interfaz ICommand.

using System.Windows.Input; 

namespace SharedViewModels.Helpers 
{ 
    public static class ICommandHelper 
    { 
     public static bool CheckBeginExecute(this ICommand command) 
     { 
      return CheckBeginExecuteCommand(command); 
     } 

     public static bool CheckBeginExecuteCommand(ICommand command) 
     { 
      var canExecute = false; 
      lock (command) 
      { 
       canExecute = command.CanExecute(null); 
       if (canExecute) 
       { 
        command.Execute(null); 
       } 
      } 

      return canExecute; 
     } 
    } 
} 

y así es como tienes que ejecutar comandos en código:

((MyViewModel)DataContext).MyCommand.CheckBeginExecute(); 

espero que esto acelerará su desarrollo sólo un poco más. :)

P.S. No olvide incluir el espacio de nombres de ICommandHelper también. (En mi caso es SharedViewModels.Helpers)

Cuestiones relacionadas