Выход из приложения или закрытие элемента управления при использовании MVVM

В моем приложении WPF я использую ViewModelLocator без IoC. Я называю статичным ViewModelLocator.Cleanup() метод, предоставленный платформой MVVM-Light от моей собственной кнопки, которая связана с "командой закрытия окна". Эта команда вызывает статический ViewModelLocator.Cleanup(), который вызывает метод Cleanup() в моем экземпляре MainWindowViewModel. Затем экземпляр метода Cleanup() устанавливает свойство, с которым MainWindow связывает его DataContext, к нулю. Сеттер на имущество поднимает PropertyChanged событие. Любопытно, что если установить для этого свойства значение null, окно не закроется.

Я пытаюсь понять, почему это так? Если я установлю главное окно DataContext к нулю, если это не то же самое, что Window.Close()? В моем случае окно и все его элементы остаются на экране. Однако, если я попытаюсь предпринять дальнейшие действия, я получу исключения нулевого указателя, указывающие на DataContext Свойство связывания действительно было установлено на ноль; это также было подтверждено в отладчике.

Я создал обходной путь, перехватив событие Application.Exit и выполнив Window.Close() в обработчике событий, чтобы создать свою собственную кнопку "Закрыть окно" (т. Е. Создать такую ​​же функциональность для моей собственной кнопки / команды, как щелчок по кнопке). кнопка X в правом верхнем углу окна). Поскольку вызов элемента пользовательского интерфейса (т. Е. Экземпляра Window) из MVVM напрямую не является дружественным к MVVM, я использовал ViewService для реализации функциональности Window.Close(), чтобы обеспечить обходной обход MVVM. Я большой поклонник идиомы ViewService (или шаблона), но я просто не думаю, что это должно быть здесь необходимо; кроме того, я мог видеть, что выход из приложения является особым случаем, который, возможно, должен быть связан с жизненным циклом приложения, и.Net, по-видимому, разрешает выход из приложения WPF только с помощью метода Window.Close().

Мысли оценили.

1 ответ

Решение

Я полагаю, что нашел ответ на свой первоначальный вопрос, в дополнение к тому, который был поднят в моем обсуждении комментариев с flq.

Во-первых, ответ на первоначальный вопрос заключается в том, что правильный способ закрыть окно - это то же, что я делал в описанном мной "обходном пути". Закрытие приложения - это процесс, инициируемый View, так как именно элемент управления Window имеет биты для того, как это сделать. Конечно, вы можете перехватить событие Application.Exit, чтобы выполнить очистку ваших ViewModels, предложить пользователю сохранить данные и т. Д.

Вопрос, поднятый мной после некоторого интересного обсуждения с flq, заключается в том, если я не просто установлю элемент управления DataContext (т. е. ViewModel) в null, чтобы освободить ресурсы View и ViewModel, как мне это сделать?

Здесь можно найти интересное обсуждение с некоторыми нюансами, но основной ответ заключается в том, что вы нашли родительский элемент управления и удалили элемент управления, который хотите закрыть, из его списка "Дети". Обратите внимание, что это другой метод с другой целью, чем просто сделать элемент управления невидимым, установив для свойства Visibility значение Collapsed. В следующем примере "this" - это удаляемый элемент управления (т. Е. "Closed"):

Panel p = (Panel) this.Parent;
p.Children.Remove(this);

Я не уверен, нужно ли вам тогда устанавливать дочерний элемент (т. Е. "This") в null, чтобы повторно запросить его ресурсы, или, если простое удаление его из визуального дерева приведет к тому, что WPF повторно запросит ресурсы; вышеупомянутое связанное обсуждение не упоминает. Как упоминалось в исходном обсуждении, вышеупомянутая методика может быть дополнена путем привязки ее к определенным событиям или использования другой логики, специфичной для приложения.

Другие вопросы по тегам