Romain
Romain

Reputation: 23

How to make a navigation service with Caliburn.Micro?

I am using Caliburn.Micro 3 in my MVVM WPF Application. I succesfully managed to implement navigation in my app by following the documentation and the samples provided.

However, I want to follow the SOLID principles and I think that using a ShellViewModel as a Conductor is a violation of the single responsibility principle.

In order to resolve this problem I created a "service" which control my navigation but I can't manage to display the ActiveItem. When I navigate, I have the ViewModel name as a string instead of the View associated with it.

public class NavigationService : Conductor<IScreen>, INavigationService
{
    public void GoTo<T>() where T : IScreen
    {
        var viewModel = IoC.Get<T>();
        ActivateItem(viewModel);
    }
}

And I use it from my "ShellViewModel".

public class ShellViewModel : PropertyChangedBase
{
    private readonly INavigationService _navigationService;

    public HomeViewModel(INavigationService navigationService)
    {
        _navigationService = navigationService;
    }

    public INavigationService NavigationService => _navigationService;

    public void ShowChartPage() => _navigationService.GoTo<TimeSeriesViewModel>();

}

The ContentControl from my ShellView :

<ContentControl Content="{Binding NavigationService.ActiveItem}" />

Am I missing something ?

Upvotes: 2

Views: 2378

Answers (1)

Il Vic
Il Vic

Reputation: 5666

The problem which causes you issue regards your XAML snippet: you are binding the Content property directly to your ViewModel (TimeSeriesViewModel), then your application cannot work as you wish. In this situation you will see just a string which represents the type of the object that you are binding to the ContentControl.

To make you application work correctly you have to use:

  1. Caliburn's naming convention i.e. you name your ContentControl in a proper way, so Caliburn can create automatically a binding for you.
  2. a Caliburn attached property called View.Model.

Both these approaches retrieve the right View for the ViewModel that your infer in the ActiveItem property of your Conductor.

In the first case your can use <ContentControl x:Name="ActiveItem" /> (but you need to create the corresponding property in the ShellViewModel class); with the second approach you can use <ContentControl cal:View.Model="{Binding NavigationService.ActiveItem}" />.

I hope that my hint and my quick explanation can help you.

Upvotes: 1

Related Questions