Как закрыть окно wpf
Перейти к содержимому

Как закрыть окно wpf

WPF MVVM: как закрыть окно

у меня есть Button который закрывает мое окно при нажатии:

Это нормально, пока я не добавлю Command до Button т.е.

Теперь он не закрывается, по-видимому, потому что я обрабатываю Command . Я могу исправить это, поставив EventHandler в и звонит this.Close() т.е.

но теперь у меня есть код в моем коде, т.е. метод SaveCommand . Я использую шаблон MVVM и SaveCommand это единственный код в моем коде позади.

Как я могу сделать это по-другому, чтобы не использовать код позади?

Примечание — установка IsCancel = «True» на кнопке ОК — плохая идея. Это свойство предназначено для кнопок Отмена. — Greg D

22 ответы

Я только что закончил блоге по этой самой теме. Вкратце, добавьте Action свойство в вашу ViewModel с помощью get и set аксессуары. Затем определите Action от твоего View конструктор. Наконец, вызовите свое действие в связанной команде, которая должна закрыть окно.

и в View конструктор:

Наконец, в любой связанной команде, которая должна закрыть окно, мы можем просто вызвать

Это сработало для меня, показалось мне довольно элегантным решением и избавило меня от кучи кода.

ответ дан 08 дек ’15, 19:12

У меня это не работает. Когда я вызываю CloseAction (), он говорит, что CloseAction имеет значение null, несмотря на код в представлении — Danielle

Извините за мое незнание, но как это не нарушает принцип разделения View и ViewModel? Если вы создаете экземпляр ViewModel в своем представлении, вы также можете не использовать MVVM. Я думаю, что лучше всего создать экземпляр вашего View и ViewModel по отдельности и установить DataContext для View вне самого представления. — Saegeoff

Решил это, сделав Action статическим свойством. Даааааааааааааааааааааааааа! — Талал Юсиф

Я понимаю, что это устаревает, но я бы сказал, что этот метод не нарушает MVVM, если нет четкого определения, которого я не знаю. В конечном итоге MVVM требует, чтобы виртуальная машина не знала о представлении, но представление должно знать о виртуальной машине. Если бы нужно было заменить представление, это никоим образом не сломало бы виртуальную машину. Произошло бы неустановленное действие, но я не думаю, что это объявление правил MVVM нарушено. Поиск «WPF DataContext Instantiation» поднимет этот самый метод во многих статьях. — летать

Вы можете выполнить инъекцию конструктора вместо инъекции свойств, чтобы избавиться от нулевой проверки: программисты.stackexchange.com/questions/177649/… this.DataContext = new ViewModel(this.Close); а затем в конструкторе ViewModel вы назначаете значение CloseAction. Это также имеет то преимущество, что CloseAction становится доступным только для получения. — ДхармаЧерепаха

Очень чистый и MVVM способ — использовать InteractionTrigger и CallMethodAction определяется в Microsoft.Interactivity.Core

Вам нужно будет добавить новое пространство имен, как показано ниже

Вам понадобится Microsoft.Xmal.Behaviours.Wpf сборка, а затем будет работать приведенный ниже код xaml.

Вам не нужен какой-либо код или что-либо еще, и вы также можете вызвать любой другой метод Window .

ответ дан 14 апр.

Это самый чистый подход, который я видел до сих пор, с точки зрения отсутствия кода и привязки ViewModel к View. Он также работает с командами. Вам нужно будет развернуть пару дополнительных DLL, и вам потребуется дополнительная работа, если вы хотите иметь возможность отменить закрытие из своей команды. Это не сильно отличается от наличия события Click в коде позади и простого вызова Close (), код обработчика событий упростит обработку сценария команды close, отменяющей событие закрытия (например, если произошла ошибка сохранения данные). Спасибо Массимилиано — Ричард Мур

Код Раджниканта больше работает в VS 2019, потому что MS сделала поведение WPF открытым и перешла в пакет NuGet Microsoft.Xaml.Behaviors.Wpf. Источником информации являются комментарии к изданию: developercommunity.visualstudio.com/content/problem/198075/… . Подробные инструкции по рефакторингу кода можно найти по адресу: devblogs.microsoft.com/dotnet/… — Эрик Вуд

Он чище, но я считаю, что это то, что должно контролироваться моделью представления, а не представлением, поскольку оно принадлежит команде, а не стандартной кнопке закрытия. — Даниэль Мёллер

Как кто-то прокомментировал, опубликованный мной код не подходит для MVVM, как насчет второго решения?

1-е решение, а не решение MVVM (я не буду удалять это как ссылку)

2-е, вероятно, лучшее решение: Использование привязанного поведения

Closing a WPF Window using MVVM and minimal code-behind

The other day I started moving all my event handlers in my application from the View’s code-behind file to the ViewModel. I accomplished this using command binding. This was all easy enough – until I came to my Close method.

You see, in the MVVM (Model – View – View Model) design pattern, the ViewModel – a class that typically contains the values you want to display in your View – shouldn’t know anything about the View. It’s OK (and quite necessary!) for the View to be aware of the ViewModel, however.

So let’s take a look at the Close button’s event handler as it originally existed in code-behind:

As you can see, it’s quite simple – only one line of code that I had to write.

So to move it to my ViewModel using command binding, I would have done something like this:

In the XAML of my button:

In the ViewModel:

All we’ve done here is move the close button event handler from the code-behind file to the ViewModel. The problem we run into, however, is with line #19. As you may be aware, the this keyword refers to the class in which it exists. This was fine in the code-behind of the Window, as this then referred to the Window, and this.Close() would successfully call the window’s Close() method. But now that we’ve moved the method into the ViewModel, this no longer refers to the Window (View), but rather the ViewModel – which doesn’t have a Close method.

So the problem, then, is how to get a method exposed by the ViewModel that references the View. Remember, the ViewModel isn’t supposed to know anything about the View in the MVVM design pattern.

The solution is quite simple: the Action object.

We’ll add an Action property to the ViewModel, but define it from the View’s code-behind file. This will let us dynamically define a reference on the ViewModel that points to the View.

On the ViewModel, we’ll simply add:

And on the View, we’ll define it as such:

At this point, we’ve assigned a delegate to the CloseAction Action property that we can simply invoke whenever we want to close the Window.

Say, for instance, we have a “Save” button on our window that we want to use to save settings from a ViewModel property, then close the window. First, we’d bind the Command property of the View’s Save button to a SaveCommand RelayCommand on the ViewModel:

And our ViewModel would contain the necessary code for the SaveCommand:

If you search the web for ways to close a window in MVVM, you’ll find various methods using several lines of code, creating more classes. Using the method described here, we can define the Close method with a single line on the ViewModel, two lines of code on the View, and invoke the Close method with a single line making a call to CloseAction().

Many thanks to my good friend Robb Allen for the tip on implementing the Action object.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *