Chciałbym obsłużyć Closing
zdarzenie (gdy użytkownik kliknie prawy górny przycisk „X”) mojego okna, aby ostatecznie wyświetlić komunikat potwierdzający lub / i anulować zamknięcie.
Wiem, jak to zrobić w kodzie: zapisz się na Closing
zdarzenie okna, a następnie użyj CancelEventArgs.Cancel
właściwości.
Ale używam MVVM, więc nie jestem pewien, czy to dobre podejście.
Myślę, że dobrym podejściem byłoby powiązanie Closing
zdarzenia z a Command
w moim ViewModel.
Próbowałem tego:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<cmd:EventToCommand Command="{Binding CloseCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
Z skojarzonym RelayCommand
w moim ViewModelu, ale nie działa (kod polecenia nie jest wykonywany).
Odpowiedzi:
Po prostu skojarzyłbym handler w konstruktorze View:
Następnie dodaj procedurę obsługi do
ViewModel
:W takim przypadku nie zyskujesz dokładnie nic poza złożonością, używając bardziej złożonego wzorca z większą liczbą pośrednią (5 dodatkowych wierszy XAML plus
Command
wzorzec).Mantra „za kodem zerowym” nie jest celem samym w sobie, chodzi o oddzielenie ViewModel od widoku . Nawet jeśli zdarzenie jest powiązane w kodzie z widokiem View,
ViewModel
nie zależy od widoku, a logika zamykająca może być testowana jednostkowo .źródło
Ten kod działa dobrze:
ViewModel.cs:
i w XAML:
przy założeniu, że:
DataContext
głównego kontenera.xmlns:command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.SL5"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
źródło
i
w<i:Interaction.Triggers>
środku i jak to zdobyć.xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
Ta opcja jest jeszcze łatwiejsza i może być dla Ciebie odpowiednia. W konstruktorze modelu widoku możesz zasubskrybować zdarzenie zamykające okno główne w następujący sposób:
Wszystkiego najlepszego.
źródło
Oto odpowiedź zgodnie ze wzorcem MVVM, jeśli nie chcesz wiedzieć o oknie (lub jakimkolwiek jego zdarzeniu) w ViewModel.
W ViewModel dodaj interfejs i implementację
W oknie dodaję wydarzenie zamknięcia. Ten kod nie przerywa wzorca MVVM. Widok może wiedzieć o modelu widoku!
źródło
IClosing
interfejs, a nie tylko zaimplementowaćOnClosing
metodę. W przeciwnym razieDataContext as IClosing
obsada się nie powiedzie i powrócinull
Rany, wygląda na to, że dzieje się tutaj dużo kodu. Staś powyżej miał właściwe podejście przy minimalnym wysiłku. Oto moja adaptacja (używająca MVVMLight, ale powinna być rozpoznawalna) ... Och, a PassEventArgsToCommand = "True" jest zdecydowanie potrzebne, jak wskazano powyżej.
(Podziękowania dla Laurent Bugnion http://blog.galasoft.ch/archive/2009/10/18/clean-shutdown-in-silverlight-and-wpf-applications.aspx )
W modelu widoku:
w ShutdownService
RequestShutdown wygląda mniej więcej tak, jak poniżej, ale w zasadzieRequestShutdown lub jakakolwiek inna nazwa decyduje o zamknięciu aplikacji, czy nie (co i tak wesoło zamknie okno):
źródło
Pytający powinien użyć odpowiedzi STAS, ale czytelnicy, którzy używają pryzmatu i nie mają galasoft / mvvmlight, mogą chcieć wypróbować to, czego użyłem:
W definicji u góry okna lub kontroli użytkownika itp. Zdefiniuj przestrzeń nazw:
A tuż pod tą definicją:
Właściwość w Twoim modelu widoku:
Dołącz delegatecommand w konstruktorze ViewModel:
Wreszcie kod, do którego chcesz dotrzeć po zamknięciu kontrolki / okna / cokolwiek:
źródło
Kusiło mnie, aby użyć programu obsługi zdarzeń w pliku App.xaml.cs, który pozwoli Ci zdecydować, czy zamknąć aplikację, czy nie.
Na przykład w pliku App.xaml.cs możesz mieć coś takiego jak następujący kod:
Następnie w kodzie MainWindowViewModel możesz mieć następujące elementy:
źródło
Zasadniczo zdarzenie okna nie może być przypisane do MVVM. Ogólnie rzecz biorąc, przycisk Zamknij powoduje wyświetlenie okna dialogowego z zapytaniem użytkownika „zapisz: tak / nie / anuluj”, co może nie zostać osiągnięte przez MVVM.
Możesz zachować procedurę obsługi zdarzenia OnClosing, w której wywołujesz Model.Close.CanExecute () i ustawia się wynik boolowski we właściwości zdarzenia. Dlatego po wywołaniu CanExecute (), jeśli true, LUB w zdarzeniu OnClosed, wywołaj Model.Close.Execute ()
źródło
Nie wykonałem zbyt wielu testów, ale wydaje się, że działa. Oto, co wymyśliłem:
źródło
W tym celu używamy AttachedCommandBehavior. Możesz dołączyć dowolne zdarzenie do polecenia w modelu widoku, unikając jakiegokolwiek kodu.
Używamy go w całym naszym rozwiązaniu i mamy prawie zerowy kod
http://marlongrech.wordpress.com/2008/12/13/attachedcommandbehavior-v2-aka-acb/
źródło
Korzystanie z zestawu narzędzi MVVM Light:
Zakładając, że w modelu widoku jest polecenie Wyjście :
Odbiera się to w widoku:
Z kolei
Closing
zdarzenie obsługuję wMainWindow
, korzystając z instancji ViewModel:CancelBeforeClose
sprawdza aktualny stan modelu widoku i zwraca wartość true, jeśli zamykanie powinno zostać zatrzymane.Mam nadzieję, że to komuś pomoże.
źródło
źródło