Reputation: 511
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
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
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
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