Estou criando um login usando um window control
para permitir que um usuário faça login em um WPF
aplicativo que estou criando.
Até agora, criei um método que verifica se o usuário inseriu as credenciais corretas para o username
e password
em a textbox
na tela de login, binding
dois properties
.
Eu consegui isso criando um bool
método, assim;
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();
}
Eu também tenho um command
que eu bind
no meu botão dentro do xaml
mesmo;
<Button Name="btnLogin" IsDefault="True" Content="Login" Command="{Binding ShowLoginCommand}" />
Ao inserir o nome de usuário e a senha ele executa o código apropriado, esteja certo ou errado. Mas como posso fechar esta janela do ViewModel quando o nome de usuário e a senha estão corretos?
Eu já tentei usar um, dialog modal
mas não deu muito certo. Além disso, em meu app.xaml, fiz algo como o seguinte, que carrega a página de login primeiro e, depois de verdadeiro, carrega o aplicativo 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);
}
}
Pergunta: Como posso fechar o Login Window control
do ViewModel?
Desde já, obrigado.
Respostas:
Você pode passar a janela para seu ViewModel usando o
CommandParameter
. Veja meu exemplo abaixo.Eu implementei um
CloseWindow
método que pega um Windows como parâmetro e o fecha. A janela é passada para o ViewModel viaCommandParameter
. Observe que você precisa definir umx:Name
para a janela que deve ser fechada. Em minha janela XAML, chamo esse método viaCommand
e passo a própria janela como um parâmetro para o ViewModel usandoCommandParameter
.ViewModel
Visão
Observe que estou usando a estrutura leve MVVM, mas o princípio se aplica a todos os aplicativos wpf.
Esta solução viola o padrão MVVM, porque o modelo de visualização não deve saber nada sobre a implementação da IU. Se você deseja seguir estritamente o paradigma de programação MVVM, você deve abstrair o tipo de visualização com uma interface.
Solução em conformidade com MVVM (antigo EDIT2)
o usuário Crono menciona um ponto válido na seção de comentários:
Você pode corrigir isso introduzindo uma interface que contém um método de fechamento.
Interface:
Seu ViewModel refatorado terá a seguinte aparência:
ViewModel
Você deve referenciar e implementar a
ICloseable
interface em sua visãoVer (código por trás)
Resposta à pergunta original: (antigo EDIT1)
Seu botão de login (CommandParameter adicionado):
Seu código:
fonte
private void LoginExecute(){this.CheckLogin();}
<- CheckLogin precisa de um parâmetro.CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
Window
objeto para o modelo de visualização quebra o padrão MVVM IMHO, porque força sua VM a saber em que está sendo visualizado. E se a visualização fosse uma guia encaixada em uma interface MDI? A maneira correta de fazer isso IMHO é passar algum tipo de interface IUIHost que implemente um método Close, e ter qualquer visão que você queira mostrar ao seu VM implementá-lo.Mantendo o MVVM, acho que usar Behaviors from the Blend SDK (System.Windows.Interactivity) ou uma solicitação de interação personalizada do Prism pode funcionar muito bem para esse tipo de situação.
Se estiver seguindo a rota do comportamento, aqui está a ideia geral:
Então, em sua janela, você apenas vincularia o CloseTrigger a um valor booleano que seria definido quando você desejasse que a janela fechasse.
Finalmente, seu DataContext / ViewModel teria uma propriedade que você definiu quando queria que a janela fechasse assim:
(defina seu Window.DataContext = new MainWindowViewModel ())
fonte
boolean
valor. Quando você disse isso, queria que eu criasse umDataTrigger
para alcançá-lo?Normalmente coloco um evento no modelo de visualização quando preciso fazer isso e, em seguida, conecto-o ao
Window.Close()
ao vincular o modelo de visualização à janelaE ao criar a janela de login
fonte
Loaded
,ContentRendered
para a janela principal, serviços de diálogo, etc.), adicionar um pouco a ela por meio do evento ViewModel é bastante simples para mim. 3 linhas de código realmente não precisam de nenhuma solução de reutilização. PS: MVVM puro é para nerds de qualquer maneira.pode ser tarde, mas aqui está a minha resposta
fonte
Bem, aqui está algo que usei em vários projetos. Pode parecer um hack, mas funciona bem.
Agora você pode ligar
DialogResult
a uma VM e definir seu valor de uma propriedade. OWindow
será fechado, quando o valor for definido.Este é um resumo do que está sendo executado em nosso ambiente de produção
Como você pode ver, estou declarando o namespace
xmlns:hlp="clr-namespace:AC.Frontend.Helper"
primeiro e depois a vinculaçãohlp:AttachedProperties.DialogResult="{Binding DialogResult}"
.A
AttachedProperty
aparência é assim. Não é o mesmo que postei ontem, mas IMHO não deve surtir efeito.fonte
<Window />
elemento conforme ilustrei no meu recorte. Eu estava com preguiça de escrever o resto (declarações de namespace etc), que geralmente também é declarado lá.datatrigger
e atribuí-lo ao botão para que funcione? Mais uma vez, desculpe pela pergunta nooby.DataTrigger¬ and setting value
true`?DataContext
oDialog
. Eu esperaria que a VM definida comoDataContext
fornecesse um comando, que define a propriedadeDialogResult
ou o que você vinculoutrue
oufalse
, para que oDialog
feche.Jeito fácil
Implementar em ViewModel
Adicionar ajudante do gerenciador de janelas geral
E feche assim no modelo de visão
fonte
WindowManager
, que por sua vez é estreitamente acoplado comView
(em termos dePresentationFramework
). Seria melhor seWindowManager
um serviço fosse passado para o viewmodel por meio de uma interface. Então você seria capaz de (digamos) migrar sua solução para uma plataforma diferente facilmente.Aqui está um exemplo simples usando o MVVM Light Messenger em vez de um evento. O modelo de visualização envia uma mensagem de fechamento quando um botão é clicado:
Em seguida, ele é recebido no código por trás da janela.
fonte
Que tal isso ?
ViewModel:
Em seu ViewModel, use CloseAction () para fechar a janela, como no exemplo acima.
Visão:
fonte
Eu sei que este é um post antigo, provavelmente ninguém iria rolar até aqui, eu sei que não. Então, depois de horas tentando coisas diferentes, eu encontrei esse blog e cara o matou. A maneira mais simples de fazer isso, experimentei e funciona como um encanto.
Blog
No ViewModel:
adicione uma propriedade Action ao ViewModel, mas defina-a a partir do arquivo code-behind do View. Isso nos permitirá definir dinamicamente uma referência no ViewModel que aponta para o View.
No ViewModel, vamos simplesmente adicionar:
E na View, vamos defini-lo como:
fonte
Você pode criar um novo manipulador de eventos no ViewModel como este.
Em seguida, defina RelayCommand para ExitCommand.
Em seguida, no conjunto de arquivos XAML
Defina o DataContext no arquivo xaml.cs e inscreva-se no evento que criamos.
fonte
Minha maneira oferecida é Declare evento em ViewModel e use blend InvokeMethodAction como abaixo.
ViewModel de amostra
A interface que pode ser fechada é a seguinte, mas não requer a execução desta ação. ICloseable ajudará na criação de um serviço de visão genérico, então se você construir visão e ViewModel por injeção de dependência, então o que você pode fazer é
Uso de ICloseable
E abaixo está o Xaml, você pode usar este xaml mesmo se não implementar a interface, ele só precisará do seu modelo de visualização para gerar CloseRquested.
fonte
Você pode usar
Messenger
do kit de ferramentas MVVMLight. em seuViewModel
enviar uma mensagem como esta:Messenger.Default.Send(new NotificationMessage("Close"));
então em seu código do windows, depois
InitializeComponent
, cadastre-se para aquela mensagem assim:você pode encontrar mais sobre o kit de ferramentas MVVMLight aqui: kit de ferramentas MVVMLight no Codeplex
Observe que não há uma "regra sem code-behind" no MVVM e você pode fazer o registro de mensagens em uma visão code-behind.
fonte
É simples. Você pode criar sua própria classe ViewModel para Login - LoginViewModel. Você pode criar view var dialog = new UserView (); dentro do seu LoginViewModel. E você pode configurar o Comando LoginCommand no botão.
e
Classe ViewModel:
fonte
Object reference not set to an instance of an object.
para o método CloseLoginView. Alguma sugestão de como resolver esse problema?Esta é uma maneira bastante simples de fazer:
YourWindow.xaml.cs
YourWindowViewModel.cs
Não vejo nada de errado com a resposta que você escolheu, apenas pensei que essa poderia ser uma maneira mais simples de fazer isso!
fonte
Você pode tratar a janela como um serviço (por exemplo, serviço de IU) e passar para o modelo de visualização por meio de uma interface , como:
Essa solução tem muitas vantagens de passar a própria visão para o modelo de visão sem ter o lado negativo de quebrar o MVVM, porque embora a visão fisicamente seja passada para o modelo de visão, este ainda não conhece o primeiro, vê apenas alguns
IMainWindowAccess
. Por exemplo, se quiséssemos migrar essa solução para outra plataforma, seria apenas uma questão de implementarIMainWindowAccess
adequadamente para, digamos, umActivity
.Estou postando a solução aqui para propor uma abordagem diferente dos eventos (embora seja na verdade muito semelhante), porque parece um pouco mais simples do que eventos para implementar (anexando / desanexando etc.), mas ainda se alinha bem com o padrão MVVM.
fonte
Você pode fechar a janela atual apenas usando o seguinte código:
fonte
System.Environment.Exit (0); no modelo de exibição funcionaria.
fonte