views:

1773

answers:

8

Hi there,

Anybody come across a clever way of closing a view in a viewmodel using MVVM?

Maybe there is a way of using binding to signal the view (window) to close?

I would really appreciate any input anyone has.

Basically i have a loginView that is bound to a loginViewModel, in the viewmodel (using binding on a command) i test to see if the login is successful and if it is i basically load up a new View (mainview) and attach its datacontext...

but i still have the loginView shown - so i need to signal it to unload..

I was also hoping for a generic solution because i am sure that i am going to need to do this sort of thing in other situations

Any ideas?

+4  A: 

Generally you would use some kind of controller/presenter/service to drive the screen activation/deactivation. MVVM is not meant to be the One Pattern to Rule Them All. You will need to combine it with other patterns in any non-trivial application.

That said, in some situations in makes sense to have a view model that manages the life cycle of child view models. For example, you might have an EditorViewModel that manages a collection of child view models - one for each document being edited. In that case, simply adding/removing to/from this collection can result in the view activating/deactivating. But this does not sound like it fits your use case.

HTH, Kent

Kent Boogaart
+7  A: 

Edit: See my blog post for a more detailed explanation.

When I need to achieve that, I use a IRequestCloseViewModel interface that I created.

This interface contains only one event: RequestClose. This event is raised by the ViewModel (which inherits from a ViewModelBase class AND implement IRequestCloseViewModel) when it wants to close its associated view.

In my app, all Window inherit from an abstract class ApplicationWindow. This abstract class is notified each time the DataContext changed and in the handler checks if the DataContext support the IRequestCloseViewModel. If this is the case, an event handler is set up to close the Window when the event is fired.

Alternatively, like Kent said, you can use screen controller that handle this mecanism in an external class.

Jalfp
Hi Jalfp, this sounds really great, Do you have an example of the abstract class that i need all windows to inherit from? .. If you have an example including Irquestcloseviewmodel also - it would be great
mark smith
I'm going to put an article on my blog in the next few hours. I'll let you know as soon as it's online :-)
Jalfp
Here it is: http://www.japf.fr/2009/09/how-to-close-a-view-from-a-viewmodel/Hope this help :)
Jalfp
Great! thank you .. i am going to take a look right now..
mark smith
Thanks! it really helped
mark smith
+1  A: 

I would use an ApplicationController which instantiates the LoginViewModel and shows the LoginView. When the user proceeds with the login screen the ApplicationController closes the LoginView and shows the MainView with its MainViewModel.

How this can be done is shown in the sample applications of the WPF Application Framework (WAF) project.

jbe
+2  A: 

You can make a command that attaches to the window and when executed closes the window. Then you can bind that command to a property on your view model, and execute the command when you want to close the window.

Nice and simple.
Darren
A: 
Rob
A: 

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>

Thejuan
+1  A: 

Not sure what MVVM framework you are using, but most contain some sort of messaging / notification solution that is easy have things register for messages which are sent. There is no reason that I can imagine that your view could not register for a message such as "CloseWindowsBoundTo" and the viewModel as the sender. Then in your view, you can just register for that message, and compare your current datacontext to the sender. If they match, close the window.

Simple, and keeps your view abstracted from your viewmodel.

Here would be my approach using MVVM-light toolkit:

In the ViewModel:

        public void notifyWindowToClose()
    {
        Messenger.Default.Send<NotificationMessage>(
            new NotificationMessage(this, "CloseWindowsBoundToMe"));
    }

And in the View:

            Messenger.Default.Register<NotificationMessage>(this, (nm) =>
            {
                if (nm.Notification == "CloseWindowsBoundToMe")
                {
                    if (nm.Sender == this.DataContext)
                        this.Close();
                }
            });
Ryan from Denver
A: 

This answer shows another way to do this:

http://stackoverflow.com/questions/501886/wpf-mvvm-newbie-how-should-the-viewmodel-close-the-form/3329467#3329467

It uses an attached property to bind the DialogResult window property to a ViewModel property. When setting the value of DialogResult to true or false, the view is closed.

Jorge Vargas