[ACCEPTED]-WPF (MVVM): Closing a view from Viewmodel?-wpftoolkit

Accepted answer
Score: 36

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

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

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

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

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

Score: 23

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

Simple, and 3 keeps your view abstracted from your viewmodel.

Here 2 would be my approach using MVVM-light toolkit:

In 1 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();
    }
});
Score: 9

I used to use the dialogcloser attached 7 behavior, but i find the below solution 6 easier where I can use it. The sample below 5 takes an example of a close button on the 4 window for simplicity.

pass the window as 3 the command parameter.

in the button xaml 2 for the view:

CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"

in the command execute method 1 in the view model:

if (parameter is System.Windows.Window)
{
    (parameter as System.Windows.Window).Close();
}
Score: 8

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

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

Score: 7

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>

0

Score: 4

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

Score: 2

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

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

Score: 2

This answer shows another way to do this:

How should the ViewModel close the form?

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

Score: 2

Just close in an EventHandler in code behind 2 and handle everything else in the view model 1 where you can use a command binding.

Score: 1

You can also do this using event. Though 11 you need like 3 lines of codes in your view 10 code behind (some MVVM purist don't like 9 this);

In your viewmodel, you create an event 8 that the view can subscribe to:

    public event CloseEventHandler Closing;
    public delegate void CloseEventHandler();
    private void RaiseClose()
    {
        if (Closing != null)
            Closing();
    }

In your, view 7 you subscribe to the event after your initializecomponent 6 method as below:

        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();
        }

You just simply call RaiseClose() when 5 you are ready to close the View from the 4 ViewModel.

You can even use this method to 3 send message to the view from the viewmodel.

The 2 event can be put in an interface to avoid 1 direct dependence of the view on the viewmodel.

Score: 0

To close the view from viewmodel i used 6 the Galasoft MVVM Light Toolkit which you 5 can download here: http://www.mvvmlight.net/

  1. create a class like this: public 4 class ClosingRequested : MessageBase { }

  2. add 3 this to your view constructor: Messenger.Default.Register(this, vm, msg=> Close());

  3. call 2 this to close your window: Messenger.Default.Send(new 1 ClosingRequested(), this);

More Related questions