wpf - galasoft - Cómo abrir una nueva ventana usando MVVM Light Toolkit
nuget mvvmlight (6)
Estoy utilizando MVVM Light toolkit en mi aplicación WPF. Me gustaría saber cuál es el mejor enfoque para abrir una nueva ventana desde una ventana existente. Tengo este MainViewModel
, que es responsable de MainWindow
de mi aplicación. Ahora, en MainView
, al hacer clic en un botón, me gustaría abrir una segunda ventana en la parte superior. Tengo RelayCommmand
al Command
del Button
. En el método RelayCommand
, puedo crear un nuevo objeto de ventana y simplemente llamar a Show()
, algo como esto:
var view2 = new view2()
view2.Show()
pero no creo que ViewModel sea responsable de crear el nuevo objeto view2
. He leído esta publicación WPF MVVM Obtener padre de VIEW MODEL donde Bugnion ha sugerido pasar el mensaje a la view1
desde viewmodel1
y luego view1
debería crear la nueva view2
. Pero no estoy seguro de qué es lo que realmente quiere decir al pasar el mensaje a la view1
? ¿Cómo debería view1
manejar el mensaje? En su código está detrás o qué?
Saludos, Nabeel
¿Por qué vas por esta ruta? Es sencillo. Si reemplaza su botón con un botón de alternancia, o un hipervínculo, o cualquier otro número de controles tipo botón, no necesita actualizar su "código detrás", es un principio básico del patrón MVVM. En su nuevo toggleButton (o lo que sea), aún termina vinculando al mismo comando exacto.
Por ejemplo, estoy creando un proyecto para un cliente que quiere tener 2 UI; una será fundamentalmente diferente en todos los sentidos, en términos de presentación. Pestañas horizontales frente a Vertical RadPanelBar (pensar Acordeón) para navegación. Ambas vistas pueden apuntar al mismo viewModel: cuando un usuario hace clic en la pestaña Orden de trabajo en la Vista 1, dispara el mismo "WorkOrderCommand" que se activa en el encabezado de la orden de trabajo en la barra del panel.
En un modelo de código subyacente, tendría que codificar dos eventos separados. Aquí solo tienes que codificar uno.
Además, le permite a un diseñador usar Blend para crear cualquier diseño que desee. Siempre que tengan los ganchos (control EventToCommand) en su lugar, a mí mismo (como desarrollador) no podría importarle menos cómo se ve el producto final.
El acoplamiento flojo es increíblemente poderoso.
A menos que me falta el punto aquí - si tuviera que usar el código detrás, ¿por qué no implementar directamente el evento button_click y abrir la segunda vista?
Lo que Bugnion parece sugerir es view1 -> click button -> relay command -> viewmodel1 -> message -> view1 -> view1.cs -> open view 2.
Vas a sacrificar la capacidad de prueba de todos modos escribiendo código subyacente, entonces ¿por qué tomar una ruta tan larga?
Encuentro que la mejor manera de abordar esto es abrir y cerrar la ventana desde ViewModel. Como sugiere this enlace,
- Crear una clase
DialogCloser
public static class DialogCloser { public static readonly DependencyProperty DialogResultProperty = DependencyProperty.RegisterAttached("DialogResult", typeof(bool?), typeof(DialogCloser), new PropertyMetadata(DialogResultChanged)); private static void DialogResultChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var window = d as Window; if (window != null) window.Close(); } public static void SetDialogResult(Window target, bool? value) { target.SetValue(DialogResultProperty, value); } }
- Cree un modelo de vista base heredando de
GalaSoft.MvvmLight.ViewModelBase
con sus miembros adicionales. Una vez hecho esto, use este modelo de vista como base para otros modelos de vista.
bool? _closeWindowFlag; public bool? CloseWindowFlag { get { return _closeWindowFlag; } set { _closeWindowFlag = value; RaisePropertyChanged("CloseWindowFlag"); } } public virtual void CloseWindow(bool? result = true) { Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => { CloseWindowFlag = CloseWindowFlag == null ? true : !CloseWindowFlag; })); }
- En la vista,
DialogCloser.DialogResult
la propiedad de dependenciaDialogCloser.DialogResult
con la propiedadCloseWindowFlag
en el modelo de vista base.
Luego puede abrir / cerrar / ocultar la ventana desde el modelo de vista.
Pasar un mensaje de ViewModel1 a View1 significa usar las capacidades de mensajería en MVVM Light Toolkit .
Por ejemplo, su ViewModel1 podría tener un comando llamado ShowView2Command, luego enviaría un mensaje para mostrar la vista.
public class ViewModel1 : ViewModelBase
{
public RelayCommand ShowView2Command { private set; get; }
public ViewModel1() : base()
{
ShowView2Command = new RelayCommand(ShowView2CommandExecute);
}
public void ShowView2CommandExecute()
{
Messenger.Default.Send(new NotificationMessage("ShowView2"));
}
}
View1 se registraría para recibir mensajes en su código y mostrar View2 cuando reciba el mensaje correcto.
public partial class View1 : UserControl
{
public View1()
{
InitializeComponent();
Messenger.Default.Register<NotificationMessage>(this, NotificationMessageReceived);
}
private void NotificationMessageReceived(NotificationMessage msg)
{
if (msg.Notification == "ShowView2")
{
var view2 = new view2();
view2.Show();
}
}
}
Puede abstraer las características específicas de la vista en servicios utilizando una interfaz genérica. En la capa de vista puede proporcionar instancias concretas de estos servicios y crear modelos de vista utilizando el contenedor IoC y la técnica de Inyección de dependencia.
En su caso, puede construir una interfaz IWindowManager o algo similar que tenga el método requerido. Esto puede ser implementado en tu capa de vista. Escribí una pequeña publicación de blog que recientemente demostró cómo abstraer el comportamiento del diálogo del modelo que no se ve. Se puede utilizar una herramienta similar para cualquier servicio relacionado con la interfaz de usuario, como navegación, MessageBox, etc.
Este enlace puede ser útil para usted http://nileshgule.blogspot.com/2011/05/silverlight-use-dialogservice-to.html
Muchas personas también usan el enfoque de disparar eventos desde los modelos de vista que están suscritos en el archivo view.cs y desde allí se realiza el MessageBox o cualquier otra acción relacionada con la interfaz de usuario. Personalmente, me gusta el enfoque de la inyección de servicios porque luego puede proporcionar múltiples implementaciones del mismo servicio. Un ejemplo simple sería cómo se maneja la navegación en las aplicaciones de Silverlight y Windows Phone 7. Puede usar el mismo modelo de vista pero inyectar implementaciones diferentes del servicio de navegación según el tipo de aplicación.
Puede hacerlo de esta manera, como si necesitara crear algunos eventos y registrarlos a la vista y llamarlos en el modelo de visualización. Abra esa ventana emergente.
Como este ejemplo
public class Mainclass : MainView
{
public delegate abc RegisterPopUp(abc A);
public RegisterPopUp POpUpEvent ;
public RelayCommand ShowCommand { private set; get; }
public void ShowCommand()
{
ShowCommand("Your parameter");
}
}
dentro de la vista MainView mn=new MainView();
Registre el evento aquí como thake mn.POpUpEvent +=
de hacer clic en el botón tab doble vez
y en los registros del método emergente, el código para abrir la ventana emergente.