Je crée une connexion en utilisant un window control
pour permettre à un utilisateur de se connecter à une WPF
application que je crée.
Jusqu'à présent, j'ai créé une méthode qui vérifie si l'utilisateur a entré les informations d'identification correctes pour le username
et password
dans un textbox
sur l'écran de connexion, binding
deux properties
.
J'ai réalisé cela en créant une bool
méthode, comme ça;
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();
}
J'ai aussi un command
que je bind
sur mon bouton dans le même xaml
genre;
<Button Name="btnLogin" IsDefault="True" Content="Login" Command="{Binding ShowLoginCommand}" />
Lorsque j'entre le nom d'utilisateur et le mot de passe, il exécute le code approprié, qu'il soit correct ou faux. Mais comment puis-je fermer cette fenêtre à partir du ViewModel lorsque le nom d'utilisateur et le mot de passe sont corrects?
J'ai déjà essayé d'utiliser un dialog modal
mais cela n'a pas tout à fait fonctionné. De plus, dans mon app.xaml, j'ai fait quelque chose comme ce qui suit, qui charge d'abord la page de connexion, puis une fois true, charge l'application réelle.
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);
}
}
Question: Comment puis-je fermer la connexion à Window control
partir du ViewModel?
Merci d'avance.
Réponses:
Vous pouvez transmettre la fenêtre à votre ViewModel en utilisant le
CommandParameter
. Voir mon exemple ci-dessous.J'ai implémenté une
CloseWindow
méthode qui prend un Windows comme paramètre et le ferme. La fenêtre est transmise au ViewModel viaCommandParameter
. Notez que vous devez définir unx:Name
pour la fenêtre qui doit être fermée. Dans ma fenêtre XAML, j'appelle cette méthode viaCommand
et transmets la fenêtre elle-même en tant que paramètre au ViewModel en utilisantCommandParameter
.VoirModèle
Vue
Notez que j'utilise le framework léger MVVM, mais le principe s'applique à chaque application wpf.
Cette solution enfreint le modèle MVVM, car le modèle de vue ne doit rien savoir de l'implémentation de l'interface utilisateur. Si vous souhaitez suivre strictement le paradigme de programmation MVVM, vous devez abstraire le type de vue avec une interface.
Solution conforme MVVM (anciennement EDIT2)
l'utilisateur Crono mentionne un point valide dans la section commentaire:
Vous pouvez résoudre ce problème en introduisant une interface contenant une méthode close.
Interface:
Votre ViewModel remanié ressemblera à ceci:
VoirModèle
Vous devez référencer et implémenter l'
ICloseable
interface dans votre vueVue (code derrière)
Réponse à la question initiale: (ancien EDIT1)
Votre bouton de connexion (paramètre de commande ajouté):
Votre code:
la source
private void LoginExecute(){this.CheckLogin();}
<- CheckLogin doit prendre un paramètre.CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
Window
objet au modèle de vue casse le modèle MVVM à mon humble avis, car cela force votre VM à savoir dans quoi il est affiché. Et si la vue était un onglet ancré dans une interface MDI à la place? La bonne façon de faire cela à mon humble avis est de passer une sorte d'interface IUIHost qui implémente une méthode Close, et d'avoir la vue que vous voulez montrer à votre vm l'implémenter.En restant MVVM, je pense que l'utilisation de Behaviors du Blend SDK (System.Windows.Interactivity) ou d'une demande d'interaction personnalisée de Prism pourrait très bien fonctionner pour ce genre de situation.
Si vous suivez la voie du comportement, voici l'idée générale:
Ensuite, dans votre fenêtre, vous lieriez simplement le CloseTrigger à une valeur booléenne qui serait définie lorsque vous vouliez que la fenêtre se ferme.
Enfin, votre DataContext / ViewModel aurait une propriété que vous définiriez lorsque vous vouliez que la fenêtre se ferme comme ceci:
(définissez votre Window.DataContext = new MainWindowViewModel ())
la source
boolean
valeur. Lorsque vous avez dit cela, vouliez-vous que je crée unDataTrigger
pour y parvenir?Je mets généralement un événement sur le modèle de vue lorsque je dois le faire, puis je le connecte au
Window.Close()
lors de la liaison du modèle de vue à la fenêtreEt lors de la création de la fenêtre de connexion
la source
Loaded
,ContentRendered
pour la fenêtre principale, les services de dialogue, etc.), y ajouter un peu via l'événement ViewModel est assez propre pour moi. 3 lignes de code n'ont pas vraiment besoin de solution de réutilisation. PS: le pur MVVM est de toute façon pour les nerds.il est peut-être tard, mais voici ma réponse
la source
Eh bien, voici quelque chose que j'ai utilisé dans plusieurs projets. Cela peut ressembler à un hack, mais cela fonctionne très bien.
Vous pouvez maintenant vous lier
DialogResult
à une machine virtuelle et définir sa valeur de propriété. LeWindow
se ferme lorsque la valeur est définie.Ceci est un résumé de ce qui fonctionne dans notre environnement de production
Comme vous pouvez le voir, je déclare d'abord l'espace de noms
xmlns:hlp="clr-namespace:AC.Frontend.Helper"
et ensuite la liaisonhlp:AttachedProperties.DialogResult="{Binding DialogResult}"
.Le
AttachedProperty
ressemble à ça. Ce n'est pas la même chose que j'ai postée hier, mais à mon humble avis, cela ne devrait avoir aucun effet.la source
<Window />
élément comme je l'ai illustré dans mon snipped. J'étais juste trop paresseux pour écrire le reste (déclarations d'espace de noms, etc.), qui y sont généralement également déclarés.datatrigger
et l'attribuer au bouton pour le faire fonctionner? Encore une fois désolé pour la question nooby.DataTrigger¬ and setting value
vrai?DataContext
duDialog
. Je m'attendrais à ce que la machine virtuelle définie commeDataContext
fournisse une commande, qui définit la propriétéDialogResult
ou tout ce que vous avez liétrue
oufalse
, de sorte que le seDialog
ferme.Moyen facile
Implémenter dans ViewModel
Ajouter un assistant de gestionnaire de fenêtres général
Et fermez-le comme ça dans viewmodel
la source
WindowManager
, qui à son tour est étroitement couplé avecView
(en termes dePresentationFramework
). Ce serait mieux siWindowManager
un service était passé à viewmodel via une interface. Ensuite, vous pourrez (par exemple) migrer facilement votre solution vers une plate-forme différente.Voici un exemple simple utilisant MVVM Light Messenger au lieu d'un événement. Le modèle de vue envoie un message de fermeture lorsqu'un bouton est cliqué:
Ensuite, il est reçu dans le code derrière la fenêtre.
la source
Et ça ?
VoirModèle:
Dans votre ViewModel, utilisez CloseAction () pour fermer la fenêtre comme dans l'exemple ci-dessus.
Vue:
la source
Je sais que c'est un vieux post, probablement personne ne ferait défiler jusqu'ici, je sais que non. Donc, après des heures à essayer différentes choses, j'ai trouvé ce blog et mec l'a tué. Le moyen le plus simple de le faire, l'a essayé et cela fonctionne comme un charme.
Blog
Dans le ViewModel:
ajoutez une propriété Action au ViewModel, mais définissez-la à partir du fichier code-behind de la vue. Cela nous permettra de définir dynamiquement une référence sur le ViewModel qui pointe vers la vue.
Sur le ViewModel, nous ajouterons simplement:
Et sur la vue, nous la définirons comme telle:
la source
Vous pouvez créer un nouveau gestionnaire d'événements dans le ViewModel comme ceci.
Définissez ensuite RelayCommand pour ExitCommand.
Then In XAML file set
Définissez le DataContext dans le fichier xaml.cs et abonnez-vous à l'événement que nous avons créé.
la source
Ma méthode proposée est de déclarer l'événement dans ViewModel et d'utiliser blend InvokeMethodAction comme ci-dessous.
Exemple de vue
I L'interface fermable est comme ci-dessous mais ne nécessite pas d'effectuer cette action. ICloseable vous aidera à créer un service de vue générique, donc si vous construisez une vue et un ViewModel par injection de dépendances, vous pouvez faire
Utilisation de ICloseable
Et ci-dessous est Xaml, vous pouvez utiliser ce xaml même si vous n'implémentez pas d'interface, il n'aura besoin que de votre modèle de vue pour déclencher CloseRquested.
la source
Vous pouvez utiliser à
Messenger
partir de la boîte à outils MVVMLight. dans votreViewModel
envoyer un message comme celui-ci:Messenger.Default.Send(new NotificationMessage("Close"));
puis dans votre code Windows derrière, après
InitializeComponent
, inscrivez-vous pour ce message comme ceci:vous pouvez en savoir plus sur la boîte à outils MVVMLight ici: Boîte à outils MVVMLight sur Codeplex
Notez qu'il n'y a pas de règle "pas de code-behind du tout" dans MVVM et que vous pouvez vous enregistrer pour les messages dans une vue code-behind.
la source
C'est simple. Vous pouvez créer votre propre classe ViewModel pour la connexion - LoginViewModel. Vous pouvez créer une vue var dialog = new UserView (); dans votre LoginViewModel. Et vous pouvez configurer la commande LoginCommand dans le bouton.
et
Classe ViewModel:
la source
Object reference not set to an instance of an object.
pour la méthode CloseLoginView. Des suggestions pour résoudre ce problème?C'est une façon dont je l'ai fait assez simplement:
YourWindow.xaml.cs
YourWindowViewModel.cs
Je ne vois rien de mal dans la réponse que vous avez choisie, j'ai juste pensé que cela pourrait être un moyen plus simple de le faire!
la source
Vous pouvez traiter window comme un service (par exemple, un service d'interface utilisateur) et se transmettre à viewmodel via une interface , en tant que telle:
Cette solution a le plus d'avantages de passer la vue elle-même à viewmodel sans avoir l'inconvénient de casser MVVM, car bien que la vue physique soit passée à viewmodel, ce dernier ne connaît toujours pas le premier, il n'en voit que quelques-uns
IMainWindowAccess
. Ainsi, par exemple, si nous voulions migrer cette solution vers une autre plate-forme, ce serait seulement une question de mise en œuvreIMainWindowAccess
correcte pour, par exemple, unActivity
.Je poste la solution ici pour proposer une approche différente de celle des événements (bien que ce soit en fait très similaire), car cela semble un peu plus simple que les événements à implémenter (attacher / détacher, etc.), mais s'aligne toujours bien avec le modèle MVVM.
la source
Vous pouvez fermer la fenêtre actuelle en utilisant simplement le code suivant:
la source
System.Environment.Exit (0); en vue le modèle fonctionnerait.
la source