Close windows wpf mvvm

WPF UserControl MVVM how to close a dialog

I’m new to MVVM and run into the problem how to open a dialog and close afterwards the dialog in its own ViewModel c#-file. Search for possible solution and found nothing suitable. My solution looks as follows, but I’m not sure if this has some drawbacks. Defined a UserControl and open it with:

In the ViewModel of the UserControl file implement:

and finally in the Close method:

What do you think about this? Hack or good solution? Thanks for feedback Beat

6 Answers 6

The ViewModel in an MVVM scenario shouldn’t have to know anything about the View . In your example, it seems to have to know a lot about the view.

Many people use many different patterns to open/close windows from the ViewModel. I prefer events/callbacks:

You can access the window more easily by referencing this.Parent from inside the UserControl (as long as it is the first content element).

A more orthodox method for what you’re trying to do would be to create a new XAML file for a Window, place an instance of your UserControl inside the Window in the XAML.

If you want your UserControl to be able to close its parent window, then add a simple Close event to the UserControl. Now in your Window XAML you can add an event handler to the close event and have the Window call Close() when the UserControl raises the event.

Then if you want to add any extra options or styling you can add it to your XAML, such as SizeToContent, WindowStartupLocation, BorderStyle, etc., to control the look and feel of your dialog.

Then when you want to show your dialog in code, you write it like:

handling window close button in wpf MVVM

is there a way to handle the window close button ie «X» in the top right corner in the viewmodel by binding to a command? or overriding the window.close command so that closing one window goes back to the previous window. Thanx.

2 Answers 2

There are several methods for this. I have pointed out two methods below.

You can use attached commands to bind the close button in your view model.

You can use Below code

NOTE: Add System.Windows.Interactivity reference

This is my RelayCommand class.

the problem was that i was closing a parent window and reopening it after closing its respective child window, causing memory leaks. I resolved by hiding the parent window and then showing it again after child window closes. I am new to wpf and windows development so i learn as i go.

Not the answer you’re looking for? Browse other questions tagged wpf mvvm or ask your own question.

Linked

Hot Network Questions

Subscribe to RSS

To subscribe to this RSS feed, copy and paste this URL into your RSS reader.

site design / logo © 2021 Stack Exchange Inc; user contributions licensed under cc by-sa. rev 2021.4.16.39093

By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.

Close Window from ViewModel [duplicate]

Im creating a Login using a window control to allow a user to login into a WPF application that I am creating.

Читайте также:  Bpm detector mac os

So far, I have created a method that checks whether the user has entered in the correct credentials for the username and password in a textbox on the login screen, binding two properties .

I have achieved this by creating a bool method, like so;

I also have a command that I bind to my button within the xaml like so;

When I enter in the username and password it executes the appropriated code, whether it being right, or wrong. But how can I close this window from the ViewModel when both username and password are correct?

I have previously tried using a dialog modal but it didn’t quite work out. Furthermore, within my app.xaml, I have done something like the following, which loads the login page first, then once true, loads the actual application.

Question: How can I close the Login Window control from the ViewModel?

Thanks in advance.

18 Answers 18

You can pass the window to your ViewModel using the CommandParameter . See my Example below.

I’ve implemented an CloseWindow Method which takes a Windows as parameter and closes it. The window is passed to the ViewModel via CommandParameter . Note that you need to define an x:Name for the window which should be close. In my XAML Window i call this method via Command and pass the window itself as a parameter to the ViewModel using CommandParameter .

Note that i’m using the MVVM light framework, but the principal applies to every wpf application.

This solution violates of the MVVM pattern, because the view-model shouldn’t know anything about the UI Implementation. If you want to strictly follow the MVVM programming paradigm you have to abstract the type of the view with an interface.

MVVM conform solution (Former EDIT2)

the user Crono mentions a valid point in the comment section:

Passing the Window object to the view model breaks the MVVM pattern IMHO, because it forces your vm to know what it’s being viewed in.

You can fix this by introducing an interface containing a close method.

Your refactored ViewModel will look like this:

You have to reference and implement the ICloseable interface in your view

View (Code behind)

Answer to the original question: (former EDIT1)

Your Login Button (Added CommandParameter):

WPF MVVM: How to close a window

I have a Button that closes my window when it’s clicked:

That’s fine until I add a Command to the Button i.e.

Now it doesn’t close presumably because I am handling the Command . I can fix this by putting an EventHandler in and calling this.Close() i.e.

but now I have code in my code behind i.e. the method SaveCommand . I am using the MVVM pattern and SaveCommand is the only code in my code behind.

How can I do this differently so as not to use code behind?

21 Answers 21

I just completed a blog post on this very topic. In a nutshell, add an Action property to your ViewModel with get and set accessors. Then define the Action from your View constructor. Finally, invoke your action in the bound command that should close the window.

In the ViewModel:

and in the View constructor:

Finally, in whatever bound command that should close the window, we can simply invoke

This worked for me, seemed like a fairly elegant solution, and saved me a bunch of coding.

Very clean and MVVM way is to use InteractionTrigger and CallMethodAction defined in Microsoft.Interactivity.Core

You will need to add a new namespace as below

Читайте также:  Хостинг серверов для линукса

You will need the Microsoft.Xmal.Behaviours.Wpf assembly and then the below xaml code will work.

You don’t need any code behind or anything else and can also call any other method of Window .

As someone commented, the code I have posted is not MVVM friendly, how about the second solution?

1st, not MVVM solution (I will not delete this as a reference)

2nd, probably better solution: Using attached behaviours

Behaviour Class Something similar to this:

I’d personally use a behaviour to do this sort of thing:

You can then attach this to your Window and Button to do the work:

I’ve added Command and CommandParameter here so you can run a command before the Window closes.

For small apps, I use my own Application Controller for showing, closing and disposing windows and DataContexts. It’s a central point in UI of an application.

It’s something like this:

and their invocations from ViewModels:

Of course you can find some restrictions in my solution. Again: I use it for small projects, and it’s enough. If you’re interested, I can post full code here or somewhere else/

I’ve tried to resolve this issue in some generic, MVVM way, but I always find that I end up unnecessary complex logic. To achieve close behavior I have made an exception from the rule of no code behind and resorted to simply using good ol’ events in code behind:

Although I wish this would be better supported using commands/MVVM, I simply think that there is no simpler and more clear solution than using events.

I use the Publish Subscribe pattern for complicated class-dependencies:

ViewModel:

Window:

You can leverage Bizmonger.Patterns to get the MessageBus.

MessageBus

Subscription

There is a useful behavior for this task which doesn’t break MVVM, a Behavior, introduced with Expression Blend 3, to allow the View to hook into commands defined completely within the ViewModel.

This behavior demonstrates a simple technique for allowing the ViewModel to manage the closing events of the View in a Model-View-ViewModel application.

This allows you to hook up a behavior in your View (UserControl) which will provide control over the control’s Window, allowing the ViewModel to control whether the window can be closed via standard ICommands.

I struggled with this topic for some time, and eventually went with the simplest approach that is still consistent with MVVM: Have the button execute the Command that does all the heavy lifting and have the button’s Click handler close the window.

XAML

XAML.cs

SaveCommand.cs

True, there is still code-behind, but there isn’t anything inherently bad about that. And it makes the most sense to me, from an OO perspective, to just tell the window to close itself.

We have the name property in the .xaml definition:

Then we have the button:

Then in the ViewModel:

Then at last, the action method:

I used this code to close a pop-up window from an application..

I found myself having to do this on a WPF application based on .Net Core 3.0, where unfortunately behaviour support was not yet officially available in the Microsoft.Xaml.Behaviors.Wpf NuGet package.

Instead, I went with a solution that made use of the Façade design pattern.

Standard command property on the view model:

Because the Close() method is already implemented by the Window class, applying the façade interface to the window is the only required code behind in the UI layer (for this simple example). The command in the presentation layer avoids any dependencies on the view/UI layer as it has no idea what it is talking to when it calls the Close method on the façade.

Читайте также:  Award cmos setup utility windows

Обработка события закрытия окна с помощью WPF/MVVM Light Toolkit

Я бы хотел обработать событие “Закрытие” (когда пользователь нажимает кнопку “Х” справа) моего окна, чтобы в конечном итоге отобразить сообщение подтверждения или/и отменить закрытие.

Я знаю, как это сделать в кодировке: подпишитесь на событие “Закрытие” окна, затем используйте свойство “CancelEventArgs.Cancel”.

Но я использую MVVM, поэтому я не уверен, что это хороший подход.

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

С помощью связанного RelayCommand в моей ViewModel, но он не работает (код команды не выполняется).

Я бы просто связал обработчик в конструкторе View:

Затем добавьте обработчик в ViewModel :

В этом случае вы ничего не получите, кроме сложности, используя более сложный шаблон с большей косвенностью (5 дополнительных строк XML плюс шаблон команд).

Мантра “с нулевым выделением кода” сама по себе не является целью, цель состоит в том, чтобы отделить ViewModel от View. Даже когда событие связано с выделенным кодом View, ViewModel не зависит от View, и логика закрытия может быть проверена модулем.

Этот код работает просто отлично:

при условии, что

  • ViewModel назначается DataContext основного контейнера.
  • xmlns:command=»clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.SL5″
  • xmlns:i=»clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity»

Эта опция еще проще и, возможно, подходит для вас. В конструкторе View Model вы можете подписаться на событие закрытия главного окна следующим образом:

Все самое лучшее.

Вот ответ в соответствии с шаблоном MVVM, если вы не хотите знать о окне (или любом его событии) в ViewModel.

В ViewModel добавьте интерфейс и реализацию

В окне Я добавляю событие Закрытие. Этот код не нарушает шаблон MVVM. View может знать о viewmodel!

Geez, похоже, здесь много кода для этого. У Стаса выше был правильный подход для минимальных усилий. Вот моя адаптация (с использованием MVVMLight, но должна быть узнаваема)… Oh и PassEventArgsToCommand = “True” определенно, как указано выше.

В модели просмотра:

RequestShutdown выглядит примерно так: butRequestShutdown или что бы то ни было, он решает, закрыть ли приложение или нет (что весело закроет окно):

Ответчик должен использовать ответ STAS, но для читателей, использующих призму, и не galasoft/mvvmlight, они могут попробовать использовать то, что я использовал:

В определении вверху для окна или usercontrol и т.д. define namespace:

И чуть ниже этого определения:

Свойство в вашей модели просмотра:

Прикрепите команду delegate в вашем конструкторе viewmodel:

Наконец, ваш код, который вы хотите достичь при закрытии элемента управления/окна/независимо:

Я хотел бы использовать обработчик событий в вашем файле App.xaml.cs, который позволит вам решить, закрывать ли приложение или нет.

Например, в вашем файле App.xaml.cs может быть что-то вроде следующего кода:

Тогда в вашем коде MainWindowViewModel вы можете иметь следующее:

В принципе, событие окна не может быть присвоено MVVM. В общем, кнопка “Закрыть” показывает диалоговое окно, чтобы спросить пользователя “сохранить: да/нет/отменить”, и это может быть не достигнуто MVVM.

Вы можете сохранить обработчик события OnClosing, где вы вызываете Model.Close.CanExecute() и устанавливаете логический результат в свойстве события.
Поэтому после вызова CanExecute(), если true, ИЛИ в событии OnClosed, вызовите Model.Close.Execute()

Я не очень много тестировал, но, похоже, он работает. Вот что я придумал:

Для этого мы используем AttachedCommandBehavior. Вы можете присоединить любое событие к команде в вашей модели просмотра, избегая любого кода.

Мы используем его во всем нашем решении и имеем почти нулевой код за

Использование инструмента MVVM Light Toolkit:

Предполагая, что в модели просмотра есть команда Exit:

Это получено в представлении:

С другой стороны, я обрабатываю событие Closing в MainWindow , используя экземпляр ViewModel:

CancelBeforeClose проверяет текущее состояние модели представления и возвращает true, если закрытие должно быть остановлено.

Оцените статью