Me gustaría manejar el Closing
evento (cuando un usuario hace clic en el botón 'X' superior derecho) de mi ventana para eventualmente mostrar un mensaje de confirmación o cancelar el cierre.
Sé cómo hacer esto en el código subyacente: suscríbase al Closing
evento de la ventana y luego use la CancelEventArgs.Cancel
propiedad.
Pero estoy usando MVVM, así que no estoy seguro de que sea un buen enfoque.
Creo que el buen enfoque sería vincular el Closing
evento a un Command
en mi ViewModel.
Intenté eso:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<cmd:EventToCommand Command="{Binding CloseCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
Con un asociado RelayCommand
en mi ViewModel pero no funciona (el código del comando no se ejecuta).
Respuestas:
Simplemente asociaría el controlador en el constructor Ver:
Luego agregue el controlador a
ViewModel
:En este caso, no gana exactamente nada excepto la complejidad al usar un patrón más elaborado con más indirección (5 líneas adicionales de
Command
patrón XAML plus ).El mantra "código cero detrás" no es el objetivo en sí mismo, el punto es desacoplar ViewModel de la Vista . Incluso cuando el evento está vinculado en el código subyacente de la Vista,
ViewModel
no depende de la Vista y la lógica de cierre puede ser probada por unidad .fuente
Este código funciona bien:
ViewModel.cs:
y en XAML:
asumiendo que:
DataContext
del contenedor principal.xmlns:command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.SL5"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
fuente
i
dentro<i:Interaction.Triggers>
y cómo obtenerlo.xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
Esta opción es aún más fácil y quizás sea adecuada para usted. En su constructor de modelo de vista, puede suscribirse al evento de cierre de la ventana principal de esta manera:
Todo lo mejor.
fuente
Aquí hay una respuesta de acuerdo con el patrón MVVM si no desea conocer la Ventana (o cualquiera de sus eventos) en ViewModel.
En ViewModel agregue la interfaz y la implementación
En la ventana agrego el evento de cierre. Este código detrás no rompe el patrón MVVM. ¡La Vista puede conocer el modelo de vista!
fuente
IClosing
interfaz, no solo implementar elOnClosing
método. De lo contrario, elDataContext as IClosing
elenco fallará y volveránull
Geez, parece que hay mucho código aquí para esto. Stas arriba tenía el enfoque correcto para un esfuerzo mínimo. Aquí está mi adaptación (usando MVVMLight pero debería ser reconocible) ... Ah, y el PassEventArgsToCommand = "True" es definitivamente necesario como se indicó anteriormente.
(crédito a Laurent Bugnion http://blog.galasoft.ch/archive/2009/10/18/clean-shutdown-in-silverlight-and-wpf-applications.aspx )
En el modelo de vista:
en el ShutdownService
RequestShutdown se parece a lo siguiente, pero básicamente RequestShutdown o como se llame decide si se cierra la aplicación o no (lo cual cerrará la ventana de todos modos):
fuente
El autor de la pregunta debería usar la respuesta STAS, pero para los lectores que usan prisma y no galasoft / mvvmlight, es posible que quieran probar lo que usé:
En la definición en la parte superior para ventana o control de usuario, etc., defina el espacio de nombres:
Y justo debajo de esa definición:
Propiedad en su modelo de vista:
Adjunte delegatecommand en su constructor de modelo de vista:
Finalmente, su código que desea alcanzar al cerrar el control / ventana / lo que sea:
fuente
Me sentiría tentado a usar un controlador de eventos dentro de su archivo App.xaml.cs que le permitirá decidir si cierra la aplicación o no.
Por ejemplo, podría tener algo como el siguiente código en su archivo App.xaml.cs:
Luego, dentro de su código MainWindowViewModel, podría tener lo siguiente:
fuente
Básicamente, el evento de ventana no puede asignarse a MVVM. En general, el botón Cerrar muestra un cuadro de diálogo para preguntarle al usuario "guardar: sí / no / cancelar", y MVVM no puede lograrlo.
Puede mantener el controlador de eventos OnClosing, donde llama al Model.Close.CanExecute () y establece el resultado booleano en la propiedad del evento. Entonces, después de la llamada CanExecute () si es verdadero, O en el evento OnClosed, llame al Model.Close.Execute ()
fuente
No he hecho muchas pruebas con esto, pero parece funcionar. Esto es lo que se me ocurrió:
fuente
Usamos AttachedCommandBehavior para esto. Puede adjuntar cualquier evento a un comando en su modelo de vista evitando cualquier código detrás.
Lo usamos en toda nuestra solución y tenemos casi cero código detrás
http://marlongrech.wordpress.com/2008/12/13/attachedcommandbehavior-v2-aka-acb/
fuente
Usando MVVM Light Toolkit:
Suponiendo que hay un comando Salir en el modelo de vista:
Esto se recibe en la vista:
Por otro lado, manejo el
Closing
evento enMainWindow
, usando la instancia de ViewModel:CancelBeforeClose
comprueba el estado actual del modelo de vista y devuelve verdadero si se debe detener el cierre.Espero que ayude a alguien.
fuente
fuente