c# - que - "¿Estás seguro?" Pregunta. ¿Parte del ViewModel o simplemente la vista?
que es mvvm en programacion (10)
Sin embargo, todo esto me parece ruido en el ViewModel. El mensaje es más un problema de la interfaz de usuario para protegerse de misclicks, etc. Para mí, esto sugiere que debería estar en la vista con un mensaje confirmado llamando a DeleteCommand.
Estoy de acuerdo; las solicitudes de este tipo deberían manejarse en la vista, ya que en última instancia, la vista es con lo que el usuario está viendo e interactuando, y no el modelo de vista. Una vez que su vista ha obtenido la confirmación del usuario de que DeleteCommand
debe invocarse, continúe e inícielo en su modelo de vista.
Tal como lo veo, las pruebas unitarias realmente no tienen nada que ver con la interacción del usuario, a menos que esté probando la vista.
He estado jugando con dónde poner "¿estás seguro?" escribe mensajes en mi aplicación MVVM WPF.
Me inclino a pensar que estos son puramente parte de la Vista. Si ViewModel expone un DeleteCommand
, entonces esperaría que ese comando se elimine inmediatamente.
Para integrar estas solicitudes en ViewModel, debería exponer un DeletePromptItem
separado, una propiedad DeletePromptItem
para vincular el prompt contra, y que también podría funcionar como un disparador para mostrar el prompt.
Incluso con esto, no hay nada que detenga una prueba unitaria llamando directamente a DeleteCommand
, a menos que ponga lógica específica en ViewModel para requerir que DeletePromptItem
coincida con el elemento proporcionado como argumento para DeleteCommand
.
Sin embargo, todo esto me parece ruido en el ViewModel. El mensaje es más un problema de la interfaz de usuario para protegerse de misclicks, etc. Para mí, esto sugiere que debería estar en la vista con un mensaje confirmado llamando a DeleteCommand.
¿Alguna idea?
Creo que depende del aviso, pero en general la lógica del código que necesita indicarle al usuario a menudo está en el modelo de vista, por ejemplo, el usuario ha presionado un botón para eliminar un elemento de la lista, se dispara un comando en la VM, se ejecuta la lógica y es aparente que esto puede afectar a otra entidad, el usuario debe entonces elegir lo que desea hacer, en este punto no debería poder pedirle a la Vista que avise al usuario para que no pueda ver ninguna otra opción sino manejar en la VM Es algo con lo que siempre me he sentido incómodo, pero simplemente escribí un método de confirmación en mi VM base que llama a un servicio de diálogo para dsiplay la solicitud y devuelve un verdadero o falso:
/// <summary>
/// A method to ask a confirmation question.
/// </summary>
/// <param name="messageText">The text to you the user.</param>
/// <param name="showAreYouSureText">Optional Parameter which determines whether to prefix the message
/// text with "Are you sure you want to {0}?".</param>
/// <returns>True if the user selected "Yes", otherwise false.</returns>
public Boolean Confirm(String messageText, Boolean? showAreYouSureText = false)
{
String message;
if (showAreYouSureText.HasValue && showAreYouSureText.Value)
message = String.Format(Resources.AreYouSureMessage, messageText);
else
message = messageText;
return DialogService.ShowMessageBox(this, message, MessageBoxType.Question) == MessageBoxResult.Yes;
}
Para mí, esta es una de esas áreas cruzadas grises a las que a veces no puedo obtener una respuesta firme en MVVM, por lo que estoy interesado en enfoques de otros poeples.
Creo que las indicaciones "¿Estás seguro?" pertenecen al modelo de vista porque su lógica de aplicación no es pura ui cosas como animaciones, etc.
así que la mejor opción sería en el método deletecommand execute para llamar a un diálogo de servicio "Are you sure".
EDITAR: código de ViewModel
IMessageBox _dialogService;//come to the viewmodel with DI
public ICommand DeleteCommand
{
get
{
return this._cmdDelete ?? (this._cmdDelete = new DelegateCommand(this.DeleteCommandExecute, this.CanDeleteCommandExecute));
}
}
poner la lógica en el método de ejecución
private void DeleteCommandExecute()
{
if (!this.CanDeleteCommandExecute())
return;
var result = this.dialogService.ShowDialog("Are you sure prompt window?", YesNo);
//check result
//go on with delete when yes
}
el servicio de diálogo puede ser cualquier cosa que desee, pero la lógica de la aplicación para verificar antes de eliminar está en su modelo de vista.
Echa un vistazo a esto:
MVVM y cuadros de diálogo de confirmación
Utilizo una técnica similar en mis modelos de vista porque creo que es parte del modelo de vista preguntar si se procederá con la eliminación o no, y no de ningún objeto visual o vista. Con la técnica descrita, su modelo no se refiere a ninguna referencia visual que no me guste sino a algún tipo de servicio que llame a un cuadro de diálogo de confirmación o un cuadro de mensaje o cualquier otra cosa.
En mi opinión, solicitar al usuario consta de dos partes:
- La lógica que determina si se debe mostrar o no el mensaje y qué se debe hacer con el resultado
- El código que realmente muestra el aviso
La Parte 2 claramente no pertenece al ViewModel.
Pero la Parte 1 pertenece allí.
Para hacer posible esta separación, utilizo un servicio que puede ser utilizado por ViewModel y para el cual puedo proporcionar una implementación específica para el entorno en el que me encuentro (WPF, Silverlight, WP7).
Esto lleva a un código como este:
interface IMessageBoxManager
{
MessageBoxResult ShowMessageBox(string text, string title,
MessageBoxButtons buttons);
}
class MyViewModel
{
IMessageBoxManager _messageBoxManager;
// ...
public void Close()
{
if(HasUnsavedChanges)
{
var result = _messageBoxManager.ShowMessageBox(
"Unsaved changes, save them before close?",
"Confirmation", MessageBoxButtons.YesNoCancel);
if(result == MessageBoxResult.Yes)
Save();
else if(result == MessageBoxResult.Cancel)
return; // <- Don''t close window
else if(result == MessageBoxResult.No)
RevertUnsavedChanges();
}
TryClose(); // <- Infrastructure method from Caliburn Micro
}
}
Este enfoque puede usarse fácilmente no solo para mostrar un cuadro de mensaje sino también para mostrar otras ventanas, como se explica en esta respuesta .
La forma en que lo he manejado en el pasado es colocar un evento en el modelo de vista que se activa cuando se debe mostrar el diálogo. La vista se engancha en el evento y se maneja mostrando el cuadro de diálogo de confirmación, y devuelve el resultado a la persona que llama a través de sus EventArgs.
Las solicitudes definitivamente no deberían formar parte de ViewModel, pero esto no necesariamente significa que la mejor solución es codificarlas en la Vista (aunque es un primer acercamiento muy razonable).
Hay dos alternativas que conozco que pueden reducir el acoplamiento entre View y ViewModel: usar un servicio de interacción y disparar solicitudes de interacción. Ambos se explican muy bien here ; es posible que desee echar un vistazo.
La idea general es que resuma cómo se realizan las interacciones asincrónicas y trabaje con algo más similar a la lógica basada en eventos, al mismo tiempo que permite que ViewModel exprese que desea interactuar con el usuario como parte de una operación ; el resultado neto es que puedes documentar esta interacción y probarla en una unidad.
Editar: Debo añadir que exploré el uso de Prism 4 con solicitudes de interacción en un prototipo de proyecto y estuve muy satisfecho con los resultados (con un poco de código de framework en funcionamiento, incluso puedes especificar lo que va a suceder en una solicitud de interacción específica en XAML!).
Personalmente, creo que es solo parte de la Vista ya que no hay datos
Sugeriría hacer esto a través de un servicio que administra las ventanas modales. Me he enfrentado a este problema hace bastante tiempo, tampoco. This publicación en el blog me ayudó mucho.
A pesar de que es una publicación de Silverlight, no debería diferir demasiado, en comparación con wpf.
EventAggregator
este tipo de problema usando el patrón EventAggregator
.
Puedes verlo here explicado