wpf mvvm prism prism-2 mediator

Ejemplo de diálogo MVVM de WPF



prism prism-2 (6)

¿Alguien tiene algún ejemplo de mostrar un diálogo de ventana usando MVVM (Prism)? - por ejemplo, una ventana de configuración de configuración cuando se ejecuta un comando.

Todos los ejemplos que he visto utilizan el patrón del mediador, lo que está bien, pero también todos tienen una referencia a la vista en el modelo de vista que no es ideal (estamos usando Plantillas de datos)

Gracias


Como entendí su comentario anterior, la pregunta no es tanto sobre mostrar los diálogos como sobre ocultarlos. Hay dos formas de resolver este problema:

  1. Use la ventana de diálogo estándar para implementar la vista. Esto requeriría tener una forma de comunicación débilmente acoplada entre View y ViewModel para que ViewModel pueda notificar a la Vista que está bien cerrar sin tener una referencia a una vista.

    Existen múltiples marcos que permitirían hacerlo: los agregadores de eventos de Prism serían uno de ellos. En este escenario, View se suscribiría a un evento (por ejemplo, MyDialogResultValidated), y al recibir el evento, establecería el DialogResult de forma accidental. ViewModel (en su SaveCommand) activará el evento si la validación fue exitosa.

  2. No use la ventana de diálogo estándar para implementar la vista. Esto requeriría tener una superposición que emularía efectivamente la modalidad.

    En este escenario, la Visibilidad de la Vista y de la superposición se unirá a la propiedad IsVisible de ViewModel que se establecerá en consecuencia mediante la implementación de SaveCommand, o siempre que ViewModel necesite mostrar la Vista.

El primer enfoque requeriría tener un poco de código en código subyacente, requiere agregar evento (s) global (es) y (posiblemente) es menos MVVM-ish. El segundo enfoque requeriría la implementación (o el uso de la implementación de otra persona) de la superposición, pero no requerirá tener código en código subyacente, no requerirá eventos globales, y es (discutible) más MVVM-ish .


Estoy de acuerdo en que usar el servicio para mostrar el diálogo según el patrón MVVM es la solución más simple. Pero, también me pregunté a mí mismo si hay 3 ensambles en mi modelo de proyecto, ViewModel, View y de acuerdo con el ensamblaje de patrones de MVVM ViewModel tiene una referencia a Model y View a Model y ViewModel, ¿dónde debería colocar la clase DialogService? Si coloco uno en el ensamblado de ViewModel, no tengo posibilidades de crear la instancia de DialogView; por otro lado, si ubicaré DialogService en el ensamblaje de Vista, ¿cómo debería inyectarlo en mi clase ViewModel?

Por lo tanto, recomendaría mirar los escenarios MVVM avanzados con Prism Part: Using Interaction Request Objects

Como ejemplo de este enfoque:

DialogViewModelBase

public abstract class DialogViewModelBase : ViewModelBase { private ICommand _ok; public ICommand Ok { get { return _ok ?? (_ok = new DelegateCommand(OkExecute, CanOkExecute)); } } protected virtual bool CanOkExecute() { return true; } protected virtual void OkExecute() { _isSaved = true; Close = true; } private ICommand _cancel; public ICommand Cancel { get { return _cancel ?? (_cancel = new DelegateCommand(CancelExecute, CanCancelExecute)); } } protected virtual bool CanCancelExecute() { return true; } protected virtual void CancelExecute() { Close = true; } private bool _isSaved = false; public bool IsSaved { get { return _isSaved; } } private bool _close = false; public bool Close { get { return _close; } set { _close = value; RaisePropertyChanged(() => Close); } } }

CreateUserStoryViewModel:

public class CreateUserStoryViewModel : DialogViewModelBase { private string _name = String.Empty; public string Name { get { return _name; } set { _name = value; RaisePropertyChanged(() => Name); } } }

CreateUserStoryRequest

private InteractionRequest<Notification> _createUserStoryRequest; public InteractionRequest<Notification> CreateUserStoryRequest { get { return _createUserStoryRequest ?? (_createUserStoryRequest = new InteractionRequest<Notification>()); } }

Comando CreateUserStory

private void CreateUserStoryExecute() { CreateUserStoryRequest.Raise(new Notification() { Content = new CreateUserStoryViewModel(), Title = "Create User Story" }, notification => { CreateUserStoryViewModel createUserStoryViewModel = (CreateUserStoryViewModel)notification.Content; if (createUserStoryViewModel.IsSaved) { _domainContext.CreateUserStory( new UserStory(){ Name = createUserStoryViewModel.Name, }); } }); }

XAML:

<!--where xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ir="clr-namespace:Microsoft.Practices.Prism.Interactivity.InteractionRequest;assembly=Microsoft.Practices.Prism.Interactivity"--> <i:Interaction.Triggers> <ir:InteractionRequestTrigger SourceObject="{Binding CreateUserStoryRequest}"> <ir:PopupChildWindowAction> <ir:PopupChildWindowAction.ChildWindow> <view:CreateUserStory /> </ir:PopupChildWindowAction.ChildWindow> </ir:PopupChildWindowAction> </ir:InteractionRequestTrigger> </i:Interaction.Triggers>


La forma en que hago esto es usar el patrón del mediador también. Cuando ViewModel quiere mostrar un diálogo, envía un mensaje que es recogido por la ventana principal de la aplicación. El mensaje contiene una instancia del ViewModel utilizado por el cuadro de diálogo.

La ventana principal luego construye una instancia de la ventana de diálogo, le pasa el modelo de vista y muestra el diálogo. El resultado del diálogo se transfiere a la persona que llama en el mensaje original.

Se ve algo como esto:

En su modelo de vista:

DialogViewModel viewModel = new DialogViewModel(...); ShowDialogMessage message = new ShowDialogMessage(viewModel); _messenger.Broadcast(message); if (message.Result == true) { ... }

En la ventana principal codebehind:

void RecieveShowDialogMessage(ShowDialogMessage message) { DialogWindow w = new DialogWindow(); w.DataContext = message.ViewModel; message.Result = w.ShowDialog(); }

Espero que esto sea suficiente para darte la idea ...



Puede que le interese la siguiente aplicación de ejemplo:

http://compositeextensions.codeplex.com

Utiliza Prism2 con el patrón PresentationModel (también conocido como MVVM). La aplicación de muestra contiene un diálogo modal.


Usaría un servicio para mostrar el diálogo. El servicio también puede vincular vistas con viewmodels.

public interface IDialogService { void RegisterView<TView, TViewModel>() where TViewModel:IDialogViewModel; bool? ShowDialog(IDialogViewModel viewModel); } public interface IDialogViewModel { bool CanClose(); void Close(); }


RegisterView solo vincula el tipo de vista con el tipo de ViewModel. Puede configurar estos enlaces en la inicialización del módulo. Esto es más simple que tratar de obtener módulos para registrar plantillas de datos en la capa superior de su aplicación.

ShowDialog Muestra el ViewModel que desea visualizar. Devuelve true, false y null para cerrar como el método Window.ShowDialog . La implementación solo crea una nueva vista de tipo TView desde su contenedor, la conecta al ViewModel proporcionado y la muestra.

IDialogViewModel proporciona un mecanismo para ViewModel para hacer la verificación y cancelar el cierre del diálogo.

Tengo una ventana de diálogo estándar, con un control de contenido. Cuando se llama a ShowDialog , crea un nuevo diálogo estándar, agrega la vista al control de contenido, conecta el ViewModel y lo muestra. El diálogo estándar ya tiene los botones [OK] y [Cancelar] con la lógica apropiada para llamar a los métodos correctos desde IDialogViewModel .