Leonardo Spina
Leonardo Spina

Reputation: 680

Caliburn Micro - how to use multiple views over a single viewmodel?

I'm trying to use several different views referring to the same viewmodel, depending on the context.

This is what I've got:

but the call (I need to do it manually from a utilities library of mine) to ViewLocator.LocateForModel(*viewModel*, null, "Overview") doesn't return anything.

What am I doing wrong? I read the CM documentatione and it seems allright...

Thanks in advance !

Upvotes: 0

Views: 2433

Answers (1)

Charleh
Charleh

Reputation: 14002

Assuming that you actually have an Overview usercontrol in the Views.Module namespace, this won't be found by CM

CM will search by removing the Model part of the original VM namespace/type name. I can't remember the exact rules, but you can customise them

For the default rules the correct namespace should be Views.Model.Overview

You might want to check out the documentation for name transformation:

https://caliburnmicro.codeplex.com/wikipage?title=View%2fViewModel%20Naming%20Conventions&referringTitle=Documentation

Also:

Since you have called your VM ModelViewModel I can only hazard a guess that the nametransformer may strip the Model from the start of your VM name too (though I think the regex only checks the end of the string so you might be ok!)

So assuming the above namespace change doesn't work you might end up with a target View name of... I don't know what!

Finally - it might be worth implementing a debug logger - CM writes a lot of info against a log interface, you just need to provide a GetLog method that provides an implementation of ILog (one that writes to the Debug stream is usually good enough for troubleshooting)

You can do this in Bootstrapper.Configure (or anywhere else that's early enough) by providing your own Func for LogManager.GetLog

LogManager.GetLog = (type) => { return new DebugLogger(); };

And implement ILog in DebugLogger (leave that one to you!)

EDIT: Try reimplementing the LocateForModel func in your bootstrapper code:

        ViewLocator.LocateForModel = (model, displayLocation, context) =>
        {
            var viewAware = model as IViewAware;
            if (viewAware != null)
            {
                var view = viewAware.GetView(context) as UIElement;
                if (view != null)
                {
                    LogManager.GetLog(typeof(ViewLocator)).Info("Using cached view for {0}.", model);
                    return view;
                }
            }

            return ViewLocator.LocateForModelType(model.GetType(), displayLocation, context);
        };

Then you can debug (this is what I've ripped from the source from v1.4 so you might want to look at the source again since 1.5 is out depending on what you are using)

https://caliburnmicro.codeplex.com/SourceControl/changeset/view/ae616b841924#src/Caliburn.Micro.Silverlight/ViewLocator.cs

Edit: It's also the Silverlight version (I've just ripped out some of the compiler conditionals) so you do want to grab the latest version from source!

Upvotes: 2

Related Questions