The usual pattern used for wpf development is mvvm.
The way I'd approach this is viewmodel first navigation.
Define a viewmodel for the window.
That would expose a property of type object ( or baseviewmodel ).
The contentcontrol would bind it's content to that property.
This would then be templated into whichever usercontrol is appropriate using the datatype mechanism to match viewmodel to view.
Changing usercontrol is then a matter of newing up a different viewmodel and setting this property to that instance.
Expose a command from the window viewmodel to do this navigation and use relativesource binding to that from your usercontrol.
This is a simple example of viewmodel first navigation:
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel>
<Button Content="Login Page"
Command="{Binding NavigateCommand}"
CommandParameter="{x:Type local:LoginViewModel}"
/>
<Button Content="User Page"
Command="{Binding NavigateCommand}"
CommandParameter="{x:Type local:UserViewModel}"
/>
</StackPanel>
<ContentControl Grid.Column="1"
Content="{Binding CurrentViewModel}"
/>
</Grid>
The viewmodel uses mvvmlight for relaycommand:
public class MainWindowViewModel : INotifyPropertyChanged
{
private object currentViewModel;
public object CurrentViewModel
{
get { return currentViewModel; }
set { currentViewModel = value; RaisePropertyChanged(); }
}
private RelayCommand<Type> navigateCommand;
public RelayCommand<Type> NavigateCommand
{
get
{
return navigateCommand
?? (navigateCommand = new RelayCommand<Type>(
vmType =>
{
CurrentViewModel = null;
CurrentViewModel = Activator.CreateInstance(vmType);
}));
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Your button would of course be in one of these usercontrols.
A relativesource binding looks like:
{Binding DataContext.NameOfCommandInWindowViewModel,
RelativeSource={RelativeSource AncestorType={x:Type MainWindow}}}
Let's say you really really don't want to learn MVVM for now.
You can get a reference to the window your usercontrol is in from it using:
Window.GetWindow(this);
There is a problem though.
The controls in a window are private members.
You can't just dip into some other object's private members and change stuff.
This means you'd have to add a public method to your window so you can call that.
This method in turn could take some other usercontrol as a parameter and set the content of one of it's controls as necessary.
Before you think "That sounds easier, I'll just do that" you should be aware that this is widely considered to be bad practice.