WPF (MVVM): Закрытие представления из Viewmodel?
Кто-нибудь сталкивается с умным способом закрытия представления в режиме просмотра с использованием MVVM?
Может быть, есть способ использовать привязку, чтобы сигнализировать о закрытии окна (окна)?
Я бы очень признателен за любой вклад, который у кого есть.
В основном у меня есть loginView, привязанный к loginViewModel, в viewmodel (используя привязку к команде). Я тестирую, чтобы проверить, успешно ли вход в систему, и если я в основном загружаю новый View (mainview) и прикрепляю его datacontext...
но у меня все еще есть показанный loginView, поэтому мне нужно сигнализировать об этом для разгрузки.
Я также надеялся на общее решение, потому что я уверен, что мне нужно будет делать подобные вещи в других ситуациях.
Любые идеи?
Ответы
Ответ 1
Изменить: см. мой пост в блоге для более подробного объяснения.
Когда мне нужно это сделать, я использую интерфейс IRequestCloseViewModel, который я создал.
Этот интерфейс содержит только одно событие: RequestClose. Это событие создается ViewModel (который наследует от класса ViewModelBase И реализует IRequestCloseViewModel), когда он хочет закрыть связанный с ним просмотр.
В моем приложении все окна наследуются от абстрактного класса ApplicationWindow. Этот абстрактный класс уведомляется каждый раз, когда DataContext изменен, и в обработчике проверяется, поддерживает ли DataContext IRequestCloseViewModel. Если это так, обработчик события настроен для закрытия окна при запуске события.
В качестве альтернативы, как сказал Кент, вы можете использовать экранный контроллер, который обрабатывает этот mecanism во внешнем классе.
Ответ 2
Не знаете, какую структуру MVVM вы используете, но большинство из них содержат какое-то решение для обмена сообщениями/уведомления, которое легко регистрировать для сообщений, которые отправляются. Нет никаких оснований полагать, что ваше мнение не могло регистрироваться для сообщения, такого как "CloseWindowsBoundTo" и viewModel в качестве отправителя. Тогда, на ваш взгляд, вы можете просто зарегистрироваться для этого сообщения и сравнить свой текущий файл данных с отправителем. Если они совпадают, закройте окно.
Простой и сохраняет ваше отражение от вашей модели.
Вот мой подход с использованием инструментария MVVM-light:
В ViewModel:
public void notifyWindowToClose()
{
Messenger.Default.Send<NotificationMessage>(
new NotificationMessage(this, "CloseWindowsBoundToMe")
);
}
И в представлении:
Messenger.Default.Register<NotificationMessage>(this, (nm) =>
{
if (nm.Notification == "CloseWindowsBoundToMe")
{
if (nm.Sender == this.DataContext)
this.Close();
}
});
Ответ 3
Раньше я использовал поведение приложения к диалоговому окну, но мне было проще найти решение, представленное ниже. В приведенном ниже примере для простоты приведен пример кнопки закрытия в окне.
передать окно в качестве параметра команды.
в кнопке xaml для просмотра:
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
в команде execute метод в модели представления:
if (parameter is System.Windows.Window)
{
(parameter as System.Windows.Window).Close();
}
Ответ 4
Как правило, вы должны использовать какой-то контроллер/презентатор/службу для управления активацией/деактивацией экрана. MVVM не предназначен для того, чтобы стать одним из них, чтобы исправить их. Вам нужно будет объединить его с другими шаблонами в любом нетривиальном приложении.
Тем не менее, в некоторых ситуациях имеет смысл иметь модель представления, которая управляет жизненным циклом моделей детского зрения. Например, у вас может быть EditorViewModel
, который управляет коллекцией моделей детского просмотра - по одному для каждого редактируемого документа. В этом случае простое добавление/удаление в/из этой коллекции может привести к активации/деактивации. Но это не похоже на то, как он подходит для вашего случая использования.
Ответ 5
http://adammills.wordpress.com/2009/07/01/window-close-from-xaml/
<Style.Triggers>
<DataTrigger Binding="{Binding CloseSignal}" Value="true">
<Setter Property="Behaviours:WindowCloseBehaviour.Close" Value="true" />
</DataTrigger>
</Style>
Ответ 6
Вы можете сделать команду, которая присоединяется к окну, и когда выполняется, закрывает окно. Затем вы можете привязать эту команду к свойству в своей модели просмотра и выполнить команду, когда вы хотите закрыть окно.
Ответ 7
Я бы использовал ApplicationController, который создает экземпляр LoginViewModel и показывает LoginView. Когда пользователь переходит к экрану входа в систему, ApplicationController закрывает LoginView и отображает MainView с помощью MainViewModel.
Как это можно сделать, показано в примерах приложений Проект WPF Application Framework (WAF).
Ответ 8
Этот ответ показывает другой способ сделать это:
Как закрыть ViewModel форму?
Он использует прикрепленное свойство, чтобы привязать свойство окна DialogResult к свойству ViewModel. При установке значения DialogResult в true или false, представление закрывается.
Ответ 9
Просто закройте в EventHandler код и обработайте все остальное в модели представления, где вы можете использовать привязку команд.
Ответ 10
Вы также можете сделать это, используя событие. Хотя вам нужен как 3 строки кода в вашем коде зрения (некоторые MVVM-пуристы не любят это);
В вашей модели просмотра вы создаете событие, на которое может подписаться вид:
public event CloseEventHandler Closing;
public delegate void CloseEventHandler();
private void RaiseClose()
{
if (Closing != null)
Closing();
}
В вашем представлении вы подписываетесь на событие после вашего метода initializecomponent, как показано ниже:
public View
{
*//The event can be put in an interface to avoid direct dependence of the view on the viewmodel. So below becomes
//ICloseView model = (ICloseView)this.DataContext;*
ProgressWindowViewModel model = (ProgressWindowViewModel)this.DataContext;
model.Closing += Model_Closing;
}
private void Model_Closing()
{
this.Close();
}
Вы просто вызываете RaiseClose(), когда будете готовы закрыть представление из ViewModel.
Вы даже можете использовать этот метод для отправки сообщения в представление из режима просмотра.
Событие может быть помещено в интерфейс, чтобы избежать прямой зависимости вида на viewmodel.
Ответ 11
Чтобы закрыть представление из viewmodel, я использовал инструмент Galasoft MVVM Light Toolkit, который вы можете скачать здесь: http://www.mvvmlight.net/
-
создайте класс следующим образом:
открытый класс ClosingRequested: MessageBase {}
-
добавьте это в конструктор вида:
Messenger.Default.Register(это, vm, msg = > Close());
-
вызовите это, чтобы закрыть окно:
Messenger.Default.Send(новый ClosingRequested(), this);