Search code examples
c#mvvmcaliburn.micro

Caliburn.Micro : locating Views when inheriting Viewmodels


I'm trying to connect multiple Viewmodels to a single View using caliburn micro. I found some solution but all seem quite heavy for something that seems to me a quite standard way of doing things.

The reason for being that is the following :

I'm implementing some views and their default ViewModels in an assembly. lets call the assembly HMI.Base with two classes

  • HMI.Base.ViewModels.BaseViewModel
  • HMI.Base.Views.BaseViewModel.

I'm then using this view from another assembly. lets call the assembly HMI.ConcreteApp

Usage is quite straightforward and overriding SelectAssemblies() does the trick so the view can be easily located.

Issues are rising when a ViewModel needs to get its data from a specific source. The solution that come to my mind is to extend my ViewModel and Add an element in its constructor being the source of my data and then do the necessary to link those data to the base viewmodel Properties.

So I create a class

  • HMI.Concrete.ViewModels.CustomViewModel

The implementation looks like this:

using HMI.Base.ViewModels;
public class CustomViewModel : BaseViewModel
{
        public CustomViewModel (IConfiguration config, ILoggerFactory loggerFactory, IEventAggregator eventAggregator, DataSourceXYZ data) : base(config, loggerFactory, eventAggregator)
        {
            Logger.LogInformation("Constructing custom viewmodel that will display as HMI.Base.Views.BaseViewModel");
        }

However the name has now changed, so the view cannot be located automatically. Is there a way to simply and clearly say "Use the base class view if no specific view exist with the same name" in the CustomViewModel ? Without having to do some more fiddling in the bootstrapper, which seems bad to me (except if it isn't ) because all needed extra information are there (we know the base viewmodel why not use the base view to display the data)


Solution

  • I will provide already an answer for the best solution I found even if I would like better:

    The solution is at this page

    In short :

    1. A custom attribute can be created to indicate the baseViewModel.
    2. The Viewlocator can be changed in the Bootstraper to take it into consideration

    And an extra step not in this article to avoid writing it in every application:

    1. create A CustomBaseBoostrapper to write it only once and use it instead of BootstrapperBase.

    It is not too bad, but I'm mainly wondering if there is not better and without changing the viewlocator.