Ich erstelle ein Login mit a window control
, damit sich ein Benutzer bei einer WPF
Anwendung anmelden kann , die ich erstelle.
Bisher habe ich eine Methode erstellt, die prüft, ob der Benutzer die richtigen Anmeldeinformationen für die username
und password
in a textbox
auf dem Anmeldebildschirm eingegeben hat , binding
zwei properties
.
Ich habe dies erreicht, indem ich eine bool
Methode wie diese geschaffen habe;
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();
}
Ich habe auch eine command
, die ich bind
zu meinem Knopf innerhalb der xaml
gleichen so;
<Button Name="btnLogin" IsDefault="True" Content="Login" Command="{Binding ShowLoginCommand}" />
Wenn ich den Benutzernamen und das Passwort eingebe, wird der entsprechende Code ausgeführt, unabhängig davon, ob er richtig oder falsch ist. Aber wie kann ich dieses Fenster im ViewModel schließen, wenn sowohl Benutzername als auch Passwort korrekt sind?
Ich habe zuvor versucht, ein zu verwenden, dialog modal
aber es hat nicht ganz geklappt. Darüber hinaus habe ich in meiner app.xaml Folgendes ausgeführt: Die Anmeldeseite wird zuerst geladen, und sobald sie wahr ist, wird die eigentliche Anwendung geladen.
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);
}
}
Frage: Wie kann ich den Login Window control
über das ViewModel schließen?
Danke im Voraus.
Antworten:
Sie können das Fenster mit dem an Ihr ViewModel übergeben
CommandParameter
. Siehe mein Beispiel unten.Ich habe eine
CloseWindow
Methode implementiert, die ein Windows als Parameter verwendet und es schließt. Das Fenster wird über an das ViewModel übergebenCommandParameter
. Beachten Sie, dass Siex:Name
für das Fenster ein Fenster definieren müssen, das geschlossen sein soll. In meinem XAML-Fenster rufe ich diese Methode über aufCommand
und übergebe das Fenster selbst als Parameter mit an das ViewModelCommandParameter
.ViewModel
Aussicht
Beachten Sie, dass ich das MVVM Light Framework verwende, aber das Prinzip gilt für jede wpf-Anwendung.
Diese Lösung verstößt gegen das MVVM-Muster, da das Ansichtsmodell nichts über die UI-Implementierung wissen sollte. Wenn Sie das MVVM-Programmierparadigma genau befolgen möchten, müssen Sie den Typ der Ansicht mit einer Schnittstelle abstrahieren.
MVVM- konforme Lösung (ehemals EDIT2)
Der Benutzer Crono erwähnt einen gültigen Punkt im Kommentarbereich:
Sie können dies beheben, indem Sie eine Schnittstelle einführen, die eine Methode zum Schließen enthält.
Schnittstelle:
Ihr überarbeitetes ViewModel sieht folgendermaßen aus:
ViewModel
Sie müssen die
ICloseable
Schnittstelle in Ihrer Ansicht referenzieren und implementierenAnsicht (Code dahinter)
Antwort auf die ursprüngliche Frage: (früher EDIT1)
Ihre Anmeldeschaltfläche (CommandParameter hinzugefügt):
Dein Code:
quelle
private void LoginExecute(){this.CheckLogin();}
<- CheckLogin muss einen Parameter aufnehmen.CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
Window
Objekts an das Ansichtsmodell wird das MVVM-Muster meiner Meinung nach unterbrochen, da Ihre VM gezwungen ist, zu wissen, in was es angezeigt wird. Was wäre, wenn die Ansicht stattdessen eine angedockte Registerkarte in einer MDI-Oberfläche wäre? Der richtige Weg, dies zu tun, besteht darin, eine Art IUIHost-Schnittstelle zu übergeben, die eine Close-Methode implementiert, und jede gewünschte Ansicht zu haben, um zu zeigen, wie Ihr VM sie implementiert.Wenn ich MVVM bleibe, denke ich, dass die Verwendung von Behaviors aus dem Blend SDK (System.Windows.Interactivity) oder einer benutzerdefinierten Interaktionsanforderung von Prism für diese Art von Situation sehr gut funktionieren könnte.
Wenn Sie den Verhaltensweg gehen, ist hier die allgemeine Idee:
Dann binden Sie in Ihrem Fenster den CloseTrigger einfach an einen booleschen Wert, der festgelegt wird, wenn das Fenster geschlossen werden soll.
Schließlich hätte Ihr DataContext / ViewModel eine Eigenschaft, die Sie festgelegt haben, als das Fenster wie folgt geschlossen werden soll:
(setze dein Window.DataContext = neues MainWindowViewModel ())
quelle
boolean
Wert erwähnt haben. Als du das gesagt hast, wolltest du, dass ich ein erschaffeDataTrigger
, um es zu erreichen?Normalerweise füge ich ein Ereignis in das Ansichtsmodell ein, wenn ich dies tun muss, und verbinde es dann mit dem,
Window.Close()
wenn das Ansichtsmodell an das Fenster gebunden wirdUnd beim Erstellen des Anmeldefensters
quelle
Loaded
,ContentRendered
für Hauptfenster, Dialogdienste usw.) und fügt hinzu , ein bisschen , um es über Ansichtsmodell Ereignis ist ziemlich sauber , wie für mich. 3 Codezeilen benötigen keine Wiederverwendbarkeitslösung. PS: reines MVVM ist sowieso für Nerds.Es mag spät sein, aber hier ist meine Antwort
quelle
Nun, hier ist etwas, das ich in mehreren Projekten verwendet habe. Es mag wie ein Hack aussehen, aber es funktioniert gut.
Jetzt können Sie eine Bindung
DialogResult
an eine VM herstellen und deren Wert für eine Eigenschaft festlegen. DasWindow
wird geschlossen, wenn der Wert eingestellt ist.Dies ist eine Zusammenfassung dessen, was in unserer Produktionsumgebung läuft
Wie Sie sehen können, deklariere ich zuerst den Namespace
xmlns:hlp="clr-namespace:AC.Frontend.Helper"
und anschließend die Bindunghlp:AttachedProperties.DialogResult="{Binding DialogResult}"
.Das
AttachedProperty
sieht so aus. Es ist nicht dasselbe, was ich gestern gepostet habe, aber meiner Meinung nach sollte es keine Wirkung haben.quelle
<Window />
Element ein, wie ich es in meinem Ausschnitt dargestellt habe. Ich war einfach zu faul, um den Rest (Namespace-Deklarationen usw.) zu schreiben, der normalerweise auch dort deklariert wird.datatrigger
und es der Schaltfläche zuweisen, damit es funktioniert? Nochmals Entschuldigung für die nooby Frage.DataTrigger¬ and setting value
wahre?DataContext
derDialog
. Ich würde erwarten, dass die VM set asDataContext
einen Befehl bereitstellt, der die EigenschaftDialogResult
oder was auch immer Sie antrue
oder gebunden habenfalse
, so dass dieDialog
geschlossen wird.Einfacher Weg
In ViewModel implementieren
Fügen Sie den allgemeinen Fenstermanager-Helfer hinzu
Und schließen Sie es so im Ansichtsmodell
quelle
WindowManager
, die wiederum eng gekoppelt ist mitView
(in Bezug aufPresentationFramework
). Es wäre besser, wennWindowManager
ein Dienst über eine Schnittstelle an viewmodel übergeben würde. Dann können Sie Ihre Lösung einfach auf eine andere Plattform migrieren.Hier ist ein einfaches Beispiel für die Verwendung des MVVM Light Messenger anstelle eines Ereignisses. Das Ansichtsmodell sendet eine Abschlussnachricht, wenn auf eine Schaltfläche geklickt wird:
Dann wird es im Code hinter dem Fenster empfangen.
quelle
Wie wäre es damit ?
ViewModel:
Verwenden Sie in Ihrem ViewModel CloseAction (), um das Fenster wie im obigen Beispiel zu schließen.
Aussicht:
quelle
Ich weiß, dass dies ein alter Beitrag ist, wahrscheinlich würde niemand so weit scrollen, ich weiß, dass ich es nicht getan habe. Nachdem ich stundenlang verschiedene Sachen ausprobiert hatte, fand ich diesen Blog und der Typ hat ihn getötet. Der einfachste Weg, dies zu tun, versuchte es und es funktioniert wie ein Zauber.
Blog
Im ViewModel:
Fügen Sie dem ViewModel eine Action-Eigenschaft hinzu, definieren Sie sie jedoch aus der CodeBehind-Datei der View. Auf diese Weise können wir dynamisch eine Referenz im ViewModel definieren, die auf die Ansicht verweist.
Im ViewModel fügen wir einfach hinzu:
Und in der Ansicht definieren wir es als solches:
quelle
So können Sie im ViewModel einen neuen Event-Handler erstellen.
Definieren Sie dann RelayCommand für ExitCommand.
Dann In XAML-Dateisatz
Legen Sie den DataContext in der Datei xaml.cs fest und abonnieren Sie das von uns erstellte Ereignis.
quelle
Mein angebotener Weg ist das Deklarieren eines Ereignisses in ViewModel und die Verwendung von Blend InvokeMethodAction wie unten.
Beispiel für ViewModel
I Die schließbare Oberfläche ist wie folgt, muss jedoch nicht ausgeführt werden. ICloseable hilft beim Erstellen eines generischen Ansichtsdienstes. Wenn Sie also Ansicht und ViewModel durch Abhängigkeitsinjektion erstellen, können Sie Folgendes tun
Verwendung von ICloseable
Und unten ist Xaml. Sie können diese Xaml auch dann verwenden, wenn Sie keine Schnittstelle implementieren. Sie benötigen lediglich Ihr Ansichtsmodell, um CloseRquested auszulösen.
quelle
Sie können das
Messenger
MVVMLight-Toolkit verwenden.ViewModel
Wenn Sie eine Nachricht wie folgt senden , registrieren Sie sichMessenger.Default.Send(new NotificationMessage("Close"));
in Ihrem Windows-Code hinter
InitializeComponent
dieser Nachricht wie folgt:Weitere Informationen zum MVVMLight-Toolkit finden Sie hier: MVVMLight-Toolkit in Codeplex
Beachten Sie, dass es in MVVM keine Regel "überhaupt kein Code-Behind" gibt und Sie sich für Nachrichten in einer Ansicht registrieren können, die Code-Behind enthält.
quelle
Es ist einfach. Sie können Ihre eigene ViewModel-Klasse für Login - LoginViewModel erstellen. Sie können view var dialog = new UserView () erstellen. in Ihrem LoginViewModel. Und Sie können Command LoginCommand in Schaltfläche einrichten.
und
ViewModel-Klasse:
quelle
Object reference not set to an instance of an object.
für die CloseLoginView-Methode ausgegeben. Irgendwelche Vorschläge, wie man dieses Problem löst?So habe ich es ganz einfach gemacht:
YourWindow.xaml.cs
YourWindowViewModel.cs
Ich sehe nichts falsches an der Antwort, die Sie gewählt haben. Ich dachte nur, dies könnte eine einfachere Möglichkeit sein, dies zu tun!
quelle
Sie können Fenster als Dienst behandeln (z. B. UI-Dienst) und sich über eine Schnittstelle an viewmodel übergeben , und zwar als solche:
Diese Lösung hat die meisten Vorteile, wenn die Ansicht selbst an das Ansichtsmodell übergeben wird, ohne dass die MVVM beeinträchtigt wird, da die physische Ansicht zwar an das Ansichtsmodell übergeben wird, das letztere jedoch noch nichts über das erstere weiß, sondern nur einige davon sieht
IMainWindowAccess
. Wenn wir diese Lösung beispielsweise auf eine andere Plattform migrieren möchten, ist es nur eine Frage derIMainWindowAccess
ordnungsgemäßen Implementierung , zActivity
.Ich poste hier die Lösung, um einen anderen Ansatz als Ereignisse vorzuschlagen (obwohl er eigentlich sehr ähnlich ist), da die Implementierung etwas einfacher zu sein scheint als das Implementieren von Ereignissen (Anhängen / Trennen usw.), aber dennoch gut mit dem MVVM-Muster übereinstimmt.
quelle
Sie können das aktuelle Fenster einfach mit dem folgenden Code schließen:
quelle
System.Environment.Exit (0); in Ansicht Modell würde funktionieren.
quelle