0

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.

1 Answer 1

1

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 UserControls (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.)

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your help. But I am bit confused where does MainContent need to reside. Right now when I follow your example and click on button the MainContent is null and private void NavigateToType1() => MainContent = Type1ViewModel, here Type1ViewModel is null.
The piece of C# code that I posted is a partial view of the ViewModel that is the data context for the main view (the last piece of XAML I posted). Type1ViewModel will be null if you haven't instantiated it yet. So, you could instantiate it and keep it in memory (perhaps in the constructor), or you could try private void NavigateToType1() => MainContent = new Type1ViewModel();.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.