Reputation: 1
I am trying to create a WPF application and for Navigation I am using the example I found at
https://rachel53461.wordpress.com/2011/12/18/navigation-with-mvvm-2/
Now, I need to navigate from one UserControl to another on button click.
Can somebody guide me how to achieve this with MVVM? Or if I should look at using some framework for Navigation.
Upvotes: 0
Views: 1136
Reputation: 5208
This will depend somewhat on context, but many times I use a technique where I have an object (or some kind of abstract class) with a name like "MainContent" inside of some ViewModel. This is responsible for holding content to be displayed in a ContentControl
.
My XAML would look something like this, where Type1View
and Type2View
would be UserControl
s (vw_Type1
and vw_Type2
are references to their namespaces), and then I would navigate between them by setting MainContent
to an instance of either Type1ViewModel
or Type2ViewModel
.
<ContentControl Content="{Binding MainContent}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type vm_Type1:Type1ViewModel}">
<vw_Type1:Type1View />
</DataTemplate>
<DataTemplate DataType="{x:Type vm_Type2:Type2ViewModel}">
<vw_Type2:Type2View />
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
This would be taken care of perhaps with a button (or two buttons in the below example) outside of the ContentControl
, that sends a command to the ViewModel containing MainContent
, which simply changes the MainContent
property, either to an existing or new instance of Type1ViewModel
or Type2ViewModel
. E.g.:
private Type1ViewModel _type1ViewModel;
public Type1ViewModel Type1ViewModel
{
get { return _type1ViewModel; }
set
{
if (_type1ViewModel != value)
{
_type1ViewModel = value;
NotifyPropertyChanged();
}
}
}
private Type2ViewModel _type2ViewModel;
public Type2ViewModel Type2ViewModel
{
get { return _type2ViewModel; }
set
{
if (_type2ViewModel != value)
{
_type2ViewModel = value;
NotifyPropertyChanged();
}
}
}
...
private ObservableObject _mainContent;
public ObservableObject MainContent
{
get { return _mainContent; }
set
{
if (_mainContent != value)
{
_mainContent = value;
NotifyPropertyChanged();
}
}
}
...
public InternalDelegateCommand NavigateToType1Command => new InternalDelegateCommand(NavigateToType1);
public InternalDelegateCommand NavigateToType2Command => new InternalDelegateCommand(NavigateToType2);
...
private void NavigateToType1() => MainContent = Type1ViewModel;
private void NavigateToType2() => MainContent = Type2ViewModel;
So to complete the XAML for this example:
<Button Content="Type 1" Command="{Binding NavigateToType1Command}" />
<Button Content="Type 2" Command="{Binding NavigateToType2Command}" />
<ContentControl Content="{Binding MainContent}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type vm_Type1:Type1ViewModel}">
<vw_Type1:Type1View />
</DataTemplate>
<DataTemplate DataType="{x:Type vm_Type2:Type2ViewModel}">
<vw_Type2:Type2View />
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
(For information on InternalDelegateCommand
, see my answer to this question.)
Upvotes: 1