Eu gostaria de lidar com o Closing
evento (quando um usuário clicar no botão 'X' superior direito) da minha janela para, eventualmente, exibir uma mensagem de confirmação ou / e cancelar o fechamento.
Eu sei como fazer isso no code-behind: assine o Closing
evento da janela e use a CancelEventArgs.Cancel
propriedade
Mas como estou usando o MVVM, não tenho certeza de que seja uma boa abordagem.
Eu acho que a boa abordagem seria vincular o Closing
evento a Command
no meu ViewModel.
Eu tentei isso:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<cmd:EventToCommand Command="{Binding CloseCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
Com um associado RelayCommand
no meu ViewModel, mas ele não funciona (o código do comando não é executado).
Respostas:
Eu simplesmente associaria o manipulador no construtor View:
Em seguida, adicione o manipulador ao
ViewModel
:Nesse caso, você não obtém exatamente nada, exceto a complexidade, usando um padrão mais elaborado e mais indireto (5 linhas extras de XAML mais
Command
padrão).O mantra "zero code-behind" não é o objetivo em si; o objetivo é desacoplar o ViewModel da View . Mesmo quando o evento é vinculado no code-behind da View,
ViewModel
isso não depende da View e a lógica de fechamento pode ser testada em unidade .fonte
Este código funciona bem:
ViewModel.cs:
e em XAML:
assumindo que:
DataContext
dos contêineres principais.xmlns:command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.SL5"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
fonte
i
dentro<i:Interaction.Triggers>
e como obtê-lo.xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
Essa opção é ainda mais fácil e talvez seja adequada para você. No construtor View Model, você pode assinar o evento de fechamento da janela principal assim:
Muito bem sucedida.
fonte
Aqui está uma resposta de acordo com o padrão MVVM, se você não quiser saber sobre a Janela (ou qualquer um de seus eventos) no ViewModel.
No ViewModel, adicione a interface e implementação
Na janela, adiciono o evento Closing. Esse código por trás não quebra o padrão MVVM. O View pode saber sobre o viewmodel!
fonte
IClosing
interface, não apenas implementar oOnClosing
método. Caso contrário, oDataContext as IClosing
elenco falhará e retornaránull
Nossa, parece que muito código está acontecendo aqui para isso. Stas acima tiveram a abordagem correta para o mínimo esforço. Aqui está minha adaptação (usando MVVMLight, mas deve ser reconhecível) ... Ah, e o PassEventArgsToCommand = "True" é definitivamente necessário, conforme indicado acima.
(crédito para Laurent Bugnion http://blog.galasoft.ch/archive/2009/10/18/clean-shutdown-in-silverlight-and-wpf-applications.aspx )
No modelo de exibição:
no ShutdownService
RequestShutdown se parece com o seguinte, mas basicamenteRequestShutdown ou o nome que ele decide decide se o aplicativo deve ou não ser encerrado (o que fecha a janela de qualquer maneira):
fonte
O solicitante deve usar a resposta STAS, mas para os leitores que usam prisma e sem galasoft / mvvmlight, eles podem tentar o que eu usei:
Na definição na parte superior da janela ou controle do usuário, etc, defina o espaço para nome:
E logo abaixo dessa definição:
Propriedade em seu viewmodel:
Anexe o comando delegat no seu construtor viewmodel:
Por fim, seu código que você deseja acessar ao fechar o controle / janela / o que for:
fonte
Eu ficaria tentado a usar um manipulador de eventos no seu arquivo App.xaml.cs que permitirá que você decida se deseja fechar o aplicativo ou não.
Por exemplo, você pode ter algo como o seguinte código no arquivo App.xaml.cs:
Em seu código MainWindowViewModel, você pode ter o seguinte:
fonte
Basicamente, o evento da janela não pode ser atribuído ao MVVM. Em geral, o botão Fechar mostra uma caixa de diálogo para solicitar ao usuário "salvar: sim / não / cancelar", e isso pode não ser alcançado pelo MVVM.
Você pode manter o manipulador de eventos OnClosing, onde chama Model.Close.CanExecute () e define o resultado booleano na propriedade event. Portanto, após a chamada CanExecute (), se verdadeira, OU no evento OnClosed, chame o Model.Close.Execute ()
fonte
Eu não fiz muitos testes com isso, mas parece funcionar. Aqui está o que eu vim com:
fonte
Usamos AttachedCommandBehavior para isso. Você pode anexar qualquer evento a um comando no seu modelo de visualização, evitando qualquer código por trás.
Nós o usamos em toda a nossa solução e temos quase zero código por trás
http://marlongrech.wordpress.com/2008/12/13/attachedcommandbehavior-v2-aka-acb/
fonte
Usando o MVVM Light Toolkit:
Supondo que exista um comando Exit no modelo de exibição:
Isso é recebido na exibição:
Por outro lado, trato de
Closing
eventoMainWindow
usando a instância do ViewModel:CancelBeforeClose
verifica o estado atual do modelo de exibição e retorna true se o fechamento deve ser interrompido.Espero que ajude alguém.
fonte
fonte