user13070
user13070

Reputation: 511

How do I close a window from its user control view model?

I have a window which hosts various UserControl's as pages. Is it possible to close the window which I have no reference to from within the usercontrol's datacontext? Simplified details:

SetupWindow

    public SetupWindow()
    {
        InitializeComponent();
        Switcher.SetupWindow = this;
        Switcher.Switch(new SetupStart());  
    }

    public void Navigate(UserControl nextPage)
    {
        this.Content = nextPage;
    }

SetupStart UserControl

<UserControl x:Class="...">
 <UserControl.DataContext>
    <local:SetupStartViewModel/>
 </UserControl.DataContext>
 <Grid>
    <Button Content="Continue" Command="{Binding ContinueCommand}"/>
 </Grid>
</UserControl>

SetupStartViewModel

    public SetupStartViewModel()
    {
    }

    private bool canContinueCommandExecute() { return true; }

    private void continueCommandExectue()
    {
        Switcher.Switch(new SetupFinish());
    }

    public ICommand ContinueCommand
    {
        get { return new RelayCommand(continueCommandExectue, canContinueCommandExecute); }
    }

Upvotes: 5

Views: 8021

Answers (3)

user13070
user13070

Reputation: 511

I managed to find a solution from an answer here: How to bind Close command to a button

View-Model:

public ICommand CloseCommand
{
    get { return new RelayCommand<object>((o) => ((Window)o).Close(), (o) => true); }
}

View:

<Button Command="{Binding CloseCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Content="Close"/>

Upvotes: 6

GazTheDestroyer
GazTheDestroyer

Reputation: 21261

I do this by having a RequestClose event in my ViewModel that it can raise when it wants the view to close.

This is then hooked up to the window's Close() command by the code that creates the window. eg

var window    = new Window();
var viewModel = new MyViewModel();

window.Content = viewModel;
viewModel.RequestClose += window.Close;

window.Show()

This way all the stuff to do with window creation is handled in one place. Neither the view, or the viewmodel know about windows.

Upvotes: 5

Andy
Andy

Reputation: 6466

Inside your user control you can find a reference to the window that's hosting it with a static method on the Window class.

var targetWindow = Window.GetWindow(this);
targetWindow.Close();

Edit:

If you have no reference to the user control that the data context is being used in you don't have a huge amount of options, if there is just 1 application window you can get away with

Application.Current.MainWindow.Close()

If there are many windows in your application and the one you want to close is in focus you could find that with something like

public Window GetFocusWindow()
{
    Window results = null;
    for (int i = 0; i < Application.Current.Windows.Count; i ++)
        if (Application.Current.Windows[i].IsFocused)
        {
            results = Application.Current.Windows[i];
            break;
        }
    return results;
}

Finally I guess (though this is pretty out there) you could loop through the applications window classes, checking the data context of every object in the visual tree until you find the reference you're after, the window can be closed from there.

Upvotes: 3

Related Questions