Estoy creando un inicio de sesión usando un window control
para permitir que un usuario inicie sesión en unWPF
aplicación que estoy creando.
Hasta ahora, he creado un método que verifica si el usuario ha ingresado las credenciales correctas para username
y password
en textbox
la pantalla de inicio de sesión, binding
dos properties
.
Lo he logrado creando un bool
método, así;
public bool CheckLogin()
{
var user = context.Users.Where(i => i.Username == this.Username).SingleOrDefault();
if (user == null)
{
MessageBox.Show("Unable to Login, incorrect credentials.");
return false;
}
else if (this.Username == user.Username || this.Password.ToString() == user.Password)
{
MessageBox.Show("Welcome " + user.Username + ", you have successfully logged in.");
return true;
}
else
{
MessageBox.Show("Unable to Login, incorrect credentials.");
return false;
}
}
public ICommand ShowLoginCommand
{
get
{
if (this.showLoginCommand == null)
{
this.showLoginCommand = new RelayCommand(this.LoginExecute, null);
}
return this.showLoginCommand;
}
}
private void LoginExecute()
{
this.CheckLogin();
}
También tengo un command
que yo bind
a mi botón dentro de lo xaml
similar;
<Button Name="btnLogin" IsDefault="True" Content="Login" Command="{Binding ShowLoginCommand}" />
Cuando ingreso el nombre de usuario y la contraseña, ejecuta el código apropiado, ya sea correcto o incorrecto. Pero, ¿cómo puedo cerrar esta ventana desde ViewModel cuando tanto el nombre de usuario como la contraseña son correctos?
Anteriormente intenté usar un dialog modal
pero no funcionó del todo. Además, dentro de mi app.xaml, he hecho algo como lo siguiente, que primero carga la página de inicio de sesión y luego, una vez verdadera, carga la aplicación real.
private void ApplicationStart(object sender, StartupEventArgs e)
{
Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
var dialog = new UserView();
if (dialog.ShowDialog() == true)
{
var mainWindow = new MainWindow();
Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
Current.MainWindow = mainWindow;
mainWindow.Show();
}
else
{
MessageBox.Show("Unable to load application.", "Error", MessageBoxButton.OK);
Current.Shutdown(-1);
}
}
Pregunta: ¿Cómo puedo cerrar el inicio Window control
de sesión desde ViewModel?
Gracias por adelantado.
Respuestas:
Puede pasar la ventana a su ViewModel usando el
CommandParameter
. Vea mi ejemplo a continuación.Implementé un
CloseWindow
método que toma un Windows como parámetro y lo cierra. La ventana se pasa a ViewModel a través deCommandParameter
. Tenga en cuenta que debe definir unx:Name
para la ventana que debe estar cerrada. En mi ventana XAML, llamo a este método a través deCommand
y paso la propia ventana como un parámetro al ViewModel usandoCommandParameter
.ViewModel
Ver
Tenga en cuenta que estoy usando el marco ligero MVVM, pero el principal se aplica a todas las aplicaciones wpf.
Esta solución viola el patrón MVVM, porque el modelo de vista no debería saber nada sobre la implementación de la interfaz de usuario. Si desea seguir estrictamente el paradigma de programación MVVM, debe abstraer el tipo de vista con una interfaz.
Solución conforme a MVVM (antes EDIT2)
el usuario Crono menciona un punto válido en la sección de comentarios:
Puede solucionar este problema introduciendo una interfaz que contiene un método de cierre.
Interfaz:
Su ViewModel refactorizado se verá así:
ViewModel
Tienes que hacer referencia e implementar la
ICloseable
interfaz en tu vista.Ver (código subyacente)
Respuesta a la pregunta original: (anteriormente EDIT1)
Su botón de inicio de sesión (parámetro de comando agregado):
Tu codigo:
fuente
private void LoginExecute(){this.CheckLogin();}
<- CheckLogin necesita incorporar un parámetro.CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
Window
objeto al modelo de vista rompe el patrón MVVM en mi humilde opinión, porque obliga a su máquina virtual a saber en qué se está viendo. ¿Qué pasa si la vista fuera una pestaña acoplada en una interfaz MDI? La forma correcta de hacer esto en mi humilde opinión es pasar algún tipo de interfaz IUIHost que implemente un método Close, y tener la vista que desee que muestre que su vm lo implementa.Siguiendo con MVVM, creo que el uso de Behaviors del Blend SDK (System.Windows.Interactivity) o una solicitud de interacción personalizada de Prism podría funcionar muy bien para este tipo de situación.
Si sigue la ruta del comportamiento, esta es la idea general:
Luego, en su ventana, simplemente vincularía CloseTrigger a un valor booleano que se establecería cuando quisiera que se cerrara la ventana.
Finalmente, su DataContext / ViewModel tendría una propiedad que establecería cuando quisiera que la ventana se cerrara así:
(establezca su Window.DataContext = new MainWindowViewModel ())
fuente
boolean
valor. Cuando dijiste eso, ¿quisiste que creara unDataTrigger
para lograrlo?Por lo general, coloco un evento en el modelo de vista cuando necesito hacer esto y luego lo conecto al
Window.Close()
al vincular el modelo de vista a la ventanaY al crear la ventana de inicio de sesión
fuente
Loaded
,ContentRendered
para la ventana principal, los servicios de diálogo, etc.), agregar un poco a través del evento ViewModel es bastante limpio para mí. 3 líneas de código realmente no necesitan ninguna solución de reutilización. PD: MVVM puro es para nerds de todos modos.puede que sea tarde, pero esta es mi respuesta
fuente
Bueno, aquí hay algo que usé en varios proyectos. Puede parecer un truco, pero funciona bien.
Ahora puede vincularse
DialogResult
a una máquina virtual y establecer su valor de propiedad. SeWindow
cerrará cuando se establezca el valor.Este es un resumen de lo que se está ejecutando en nuestro entorno de producción.
Como puede ver,
xmlns:hlp="clr-namespace:AC.Frontend.Helper"
primero declaro el espacio de nombres y luego el enlacehlp:AttachedProperties.DialogResult="{Binding DialogResult}"
.Se
AttachedProperty
ve así. No es lo mismo que publiqué ayer, pero en mi humilde opinión, no debería tener ningún efecto.fuente
<Window />
elemento como lo ilustré en mi recorte. Era demasiado vago para escribir el resto (declaraciones de espacio de nombres, etc.), que generalmente también se declara allí.datatrigger
y asignarlo al botón para que funcione? Nuevamente perdón por la pregunta de Nooby.DataTrigger¬ and setting value
verdadero`?DataContext
delDialog
. Yo esperaría que la VM establecida comoDataContext
proporcione un comando, que establece la propiedadDialogResult
o lo que sea que haya vinculadotrue
ofalse
, para que seDialog
cierre.Manera fácil
Implementar en ViewModel
Agregar asistente de administrador de ventanas general
Y ciérralo así en viewmodel
fuente
WindowManager
, que a su vez está estrechamente acoplado conView
(en términos dePresentationFramework
). Sería mejor siWindowManager
se pasara un servicio a viewmodel a través de una interfaz. Entonces podría (digamos) migrar su solución a una plataforma diferente fácilmente.A continuación, se muestra un ejemplo sencillo que utiliza MVVM Light Messenger en lugar de un evento. El modelo de vista envía un mensaje de cierre cuando se hace clic en un botón:
Luego se recibe en el código detrás de la ventana.
fuente
¿Qué tal esto ?
ViewModel:
En su ViewModel, use CloseAction () para cerrar la ventana como en el ejemplo anterior.
Ver:
fuente
Sé que esta es una publicación antigua, probablemente nadie se desplazaría hasta aquí, sé que no lo hice. Entonces, después de horas de probar cosas diferentes, encontré este blog y el tipo lo mató. La forma más sencilla de hacer esto, probé y funciona como un encanto.
Blog
En ViewModel:
agregue una propiedad Action al ViewModel, pero defínela desde el archivo de código subyacente de View. Esto nos permitirá definir dinámicamente una referencia en el ViewModel que apunta a la Vista.
En ViewModel, simplemente agregaremos:
Y en la Vista, lo definiremos como tal:
fuente
Puede crear un nuevo controlador de eventos en ViewModel de esta manera.
Luego defina RelayCommand para ExitCommand.
Luego, en el conjunto de archivos XAML
Configure el DataContext en el archivo xaml.cs y suscríbase al evento que creamos.
fuente
Mi forma ofrecida es Declarar evento en ViewModel y usar la combinación InvokeMethodAction como se muestra a continuación.
Modelo de vista de muestra
I La interfaz que se puede cerrar es la siguiente, pero no es necesario realizar esta acción. ICloseable ayudará a crear un servicio de vista genérico, por lo que si construye una vista y un modelo de vista por inyección de dependencia, lo que puede hacer es
Uso de ICloseable
Y a continuación se muestra Xaml, puede usar este xaml incluso si no implementa la interfaz, solo necesitará su modelo de vista para generar CloseRquested.
fuente
Puede utilizar
Messenger
desde el kit de herramientas MVVMLight. en suViewModel
envíe un mensaje como este:Messenger.Default.Send(new NotificationMessage("Close"));
luego en su código de Windows detrás, después
InitializeComponent
, regístrese para ese mensaje como este:puede encontrar más sobre el kit de herramientas MVVMLight aquí: Kit de herramientas MVVMLight en Codeplex
Tenga en cuenta que no hay una "regla de ningún código subyacente" en MVVM y puede registrarse para recibir mensajes en una vista de código subyacente.
fuente
Es sencillo. Puede crear su propia clase ViewModel para Login - LoginViewModel. Puede crear la vista var dialog = new UserView (); dentro de su LoginViewModel. Y puede configurar Command LoginCommand en button.
y
Clase ViewModel:
fuente
Object reference not set to an instance of an object.
para el método CloseLoginView. ¿Alguna sugerencia de cómo resolver ese problema?Esta es una forma en que lo hice de manera bastante simple:
YourWindow.xaml.cs
YourWindowViewModel.cs
No veo nada malo en la respuesta que eligió, ¡solo pensé que esta podría ser una forma más simple de hacerlo!
fuente
Puede tratar la ventana como un servicio (por ejemplo, servicio de interfaz de usuario) y pasar a viewmodel a través de una interfaz , como tal:
Esta solución tiene la mayoría de las ventajas de pasar la vista en sí a viewmodel sin tener la desventaja de romper MVVM, porque aunque la vista física se pasa a viewmodel, este último todavía no sabe sobre el primero, solo ve algunos
IMainWindowAccess
. Entonces, por ejemplo, si quisiéramos migrar esta solución a otra plataforma, solo sería cuestión de implementarlaIMainWindowAccess
correctamente para, digamos, unActivity
.Estoy publicando la solución aquí para proponer un enfoque diferente a los eventos (aunque en realidad es muy similar), porque parece un poco más simple que los eventos de implementar (adjuntar / separar, etc.), pero aún se alinea bien con el patrón MVVM.
fuente
Puede cerrar la ventana actual simplemente usando el siguiente código:
fuente
System.Environment.Salir (0); en el modelo de vista funcionaría.
fuente