¿Cómo se han implementado con éxito el cuadro de mensaje.Show() funcionalidad en MVVM?

StackOverflow https://stackoverflow.com/questions/1098023

  •  11-09-2019
  •  | 
  •  

Pregunta

Tengo una aplicación de WPF que pide el cuadro de mensaje.Show() camino de regreso en el ViewModel (para comprobar si el usuario realmente quiere eliminar). Esto funciona en realidad, pero va en contra del grano de MVVM desde el ViewModel no debe explícitamente determinar lo que sucede en la Vista.

Así que ahora estoy pensando ¿cómo puedo aplicar mejor el cuadro de mensaje.Show() funcionalidad en mi MVVM de la aplicación, las opciones de:

  1. Yo podría haber un mensaje con el texto "¿estás seguro de que...?", junto con dos botones Sí y No todo en una Frontera, en mi XAML, y crear un trigger en la plantilla para que se derrumbó/visible basado en un ViewModelProperty llamado AreYourSureDialogueBoxIsVisible, y , a continuación, cuando siento la necesidad de este cuadro de diálogo " asignar AreYourSureDialogueBoxIsVisible a "true", y también se encargan de los dos botones a través de DelegateCommand de vuelta en mi ViewModel.

  2. Yo también podría de alguna manera tratar de manejar esto con desencadena en XAML para que el botón de Borrar en realidad sólo hace algunos Frontera elemento aparece con el mensaje y los botones en ella, y el botón Sí lo hizo el de eliminar realmente.

Ambas soluciones parecen ser demasiado complejo de lo que solía ser un par de líneas de código con el cuadro de mensaje.Show().

¿De qué manera ha implementado con éxito de los Cuadros de Diálogo en su MVVM aplicaciones?

¿Fue útil?

Solución

De las dos que mencionas, yo prefiero la opción #2.El botón Eliminar en la página sólo hace que el "Diálogo Confirmar eliminación" aparecen.El "Diálogo Confirmar eliminación" en realidad se inicia la eliminación.

Ha revisado Karl Shifflett del WPF Línea De Negocio de Diapositivas y Demos?Yo sé que él hace algo como esto.Voy a tratar de recordar donde.

EDITAR:Echa un vistazo Demo #11 "Validación de Datos en MVVM" (EditContactItemsControlSelectionviewmodel.DeleteCommand).Karl llama a un emergente de la ViewModal (Qué!?:-).De hecho, me gusta tu idea mejor.Parece más fácil de la Prueba de Unidad.

Otros consejos

Servicios para el rescate.El uso de Onyx (descargo de responsabilidad, yo soy el autor) esto es tan fácil como:

public void Foo()
{
    IDisplayMessage dm = this.View.GetService<IDisplayMessage>();
    dm.Show("Hello, world!");
}

En una aplicación en ejecución, este va a llamar indirectamente MessageBox.Show("Hola, mundo!").Cuando se prueba, el IDisplayMessage servicio puede ser burlado y siempre a la Perspective hacer todo lo que desea lograr durante la prueba.

Para ampliar Decano de la Tiza de la respuesta ahora que su vínculo se extingue:

En la Aplicación.xaml.cs archivo que conectar el diálogo de confirmación para el viewmodel.

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);
    var confirm = (Func<string, string, bool>)((msg, capt) => MessageBox.Show(msg, capt, MessageBoxButton.YesNo) == MessageBoxResult.Yes);
    var window = new MainWindowView();
    var viewModel = new MainWindowViewModel(confirm);
    window.DataContext = viewModel;
    ...
}

En la vista (MainWindowView.xaml) tenemos un botón que llama a un comando en el ViewModel

<Button Command="{Binding Path=DeleteCommand}" />

El viewmodel (MainWindowViewModel.cs) utiliza un delegado del comando para mostrar el "are you sure?" diálogo y realizar la acción.En este ejemplo se trata de un SimpleCommand similar a este, pero la aplicación de ICommand debe hacer.

private readonly Func<string, string, bool> _confirm;

//constructor
public MainWindowViewModel(Func<string, string, bool> confirm)
{
    _confirm = confirm;
    ...
}

#region Delete Command
private SimpleCommand _deleteCommand;
public ICommand DeleteCommand
{
    get { return _deleteCommand ?? (_deleteCommand = new SimpleCommand(ExecuteDeleteCommand, CanExecuteDeleteCommand)); }
}

public bool CanExecuteDeleteCommand()
{
    //put your logic here whether to allow deletes
    return true;
}

public void ExecuteDeleteCommand()
{
    bool doDelete =_confirm("Are you sure?", "Confirm Delete");
    if (doDelete)
    {
        //delete from database
        ...
    }
}
#endregion

Acabo de crear una interfaz (IMessageDisplay o similar) que se inyecta en la VM, y tiene métodos como un MessageBox (ShowMessage (), etc).Puede implementar que el uso de un estándar messagebox, o algo más de WPF específicos (yo uso este en CodePlex un chico llamado Prajeesh).

De esa manera todo está separado y comprobables.

¿Qué acerca de la generación de un Evento como "MessageBoxRequested" manejado en el código subyacente de la Vista (de todos modos es solo en la Vista de código, así que no veo ningún problema con tener este código en el código subyacente).

He hecho una simple MessageBox contenedor de control para el uso en pura MVVM solución y sigue permitiendo que la unidad de pruebas de capacidad.Los detalles están en mi blog http://geekswithblogs.net/mukapu/archive/2010/03/12/user-prompts-messagebox-with-mvvm.aspx

mukapu

He implementado un Comportamiento que escucha un Mensaje desde la Perspective.Se basa en Laurent Bugnion solución, pero ya que no utiliza código de atrás y es más reutilizable, creo que es más elegante.

Échale un vistazo aquí

Silverlight y WPF cuadros de mensaje

MVVM compatibles

http://slwpfmessagebox.codeplex.com/

Sólo en caso de que alguien más está todavía la lectura y la insatisfecho:

Yo sólo quería manejar 'notificación' tipo de cuadros de mensaje (es decir,No me importa acerca de la DialogResult), pero el problema que tengo con la mayoría de las soluciones que he leído es que parecen obligar indirectamente a la implementación de la Vista (que es, en la actualidad tengo un MessageBox.Show, pero si más tarde decide solo de violín con la visibilidad de una oculta el panel directamente en mi Opinión, que no de malla muy bien con un INotification la interfaz pasa a la ViewModel).

Así que me fui para una rápida y sucia:

El ViewModel tiene un string NotificationMessage la propiedad, con los cambios notificados a PropertyChanged.

La Vista se suscribe a PropertyChanged, y , si ve que el NotificationMessage propiedad venir a través de, hace lo que quiere.

OK, así que esto significa que la Vista ha de código subyacente, y el nombre de PropertyChanged es rígida, pero sería codificada en el código XAML de todos modos.Y eso significa que evitar todas las cosas como convertidores de Visibilidad y las propiedades de decir si la notificación es todavía visible o no.

(Es cierto que esto es sólo para un número limitado de casos de uso (dispara y olvida), no he dado mucho pensamiento a cómo yo podría extender.)

Me acaba de tirar de la VM.Yo no quiero tener que utilizar algún otro servicio o escribir mi propia sólo para lanzar un messagebox.

Recientemente me encontré con este problema, donde he tenido que cambiar el cuadro de mensaje.Mostrar en el Viewmodel totalmente con algunas MVVM queja mensaje mecanismo de la caja.

Para lograr esto he utilizado InteractionRequest<Notification> y InteractionRequest<Confirmation> junto con la interacción de factores desencadenantes y escribí mi propio punto de vista para el cuadro de mensaje.

Lo que he implementado es publicado aquí

Hay tantas respuestas sobre este tema, que varían desde la creación de una clase personalizada para el uso de bibliotecas de terceros.Yo diría que el uso de una biblioteca de terceros si se quiere enfriar pop ups con buenos efectos visuales.

Pero si sólo desea utilizar el regular cuadro de mensaje de microsoft para su aplicación WPF aquí es un MVVM/unidad de prueba amistoso de la aplicación:

Inicialmente pensé que iba a heredar sólo desde el cuadro de mensaje y se envuelve con una interfaz pero no podía debido a un cuadro de Mensaje no tener un constructor público, así que aquí está la solución "fácil":

Descompilar cuadro de Mensaje en visual studio puede ver todas las sobrecargas de método, he comprobado que yo quería entonces se crea una nueva clase y añadido los métodos, lo envolvió con una interfaz y ta-da!Ahora usted puede utilizar ninject para obligar a la interfaz y clase, inyectar y el uso de Moq para la prueba de unidad e.t.c.

Crear una interfaz (sólo añadió un par de las sobrecargas, ya que no necesito de todos ellos):

public interface IMessageBox
    {
        /// <summary>Displays a message box that has a message, title bar caption, and button; and that returns a result.</summary>          
        MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button);

        /// <summary>Displays a message box that has a message, title bar caption, button, and icon; and that returns a result.</summary>           
        MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon);

        /// <summary>Displays a message box that has a message and title bar caption; and that returns a result.</summary>            
        MessageBoxResult Show(string messageBoxText, string caption);
    }

Luego tenemos a la clase que herede de ella:

public class MessageBoxHelper : IMessageBox
    {
        /// <summary>Displays a message box that has a message, title bar caption, button, and icon; and that returns a result.</summary>            
        public MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button,
            MessageBoxImage icon)
        {
            return MessageBox.Show(messageBoxText, caption, button, icon, MessageBoxResult.None,
                MessageBoxOptions.None);
        }

        /// <summary>Displays a message box that has a message, title bar caption, and button; and that returns a result.</summary>            
        public MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button)
        {
            return MessageBox.Show(messageBoxText, caption, button, MessageBoxImage.None, MessageBoxResult.None,
                MessageBoxOptions.None);
        }

        /// <summary>Displays a message box that has a message and title bar caption; and that returns a result.</summary>            
        public MessageBoxResult Show(string messageBoxText, string caption)
        {
            return MessageBox.Show(messageBoxText, caption, MessageBoxButton.OK, MessageBoxImage.None,
                MessageBoxResult.None, MessageBoxOptions.None);
        }

        /// <summary>Displays a message box that has a message and that returns a result.</summary>           
        public MessageBoxResult Show(string messageBoxText)
        {
            return MessageBox.Show(messageBoxText, string.Empty, MessageBoxButton.OK, MessageBoxImage.None,
                MessageBoxResult.None, MessageBoxOptions.None);
        }
    }

Ahora sólo tiene que utilizar esta cuando la inyección de correo.t.c y auge de la u tiene una endeble abstracción que hará el truco...lo cual está bien, dependiendo de donde usted va a usar.Mi caso es una sencilla aplicación pensada para hacer un par de cosas, así que no hay punto sobre la ingeniería de una solución.Espero que esto ayude a alguien.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top