2

I have a WPF application, using Caliburn Micro, and StructureMap for DI.

On my window, I have a ContentControl, the name of which is a property on my view model - at runtime Caliburn successfully locates the correct view based on the type of this property and displays it in that area.

At design-time, though, an exception is thrown: "InvalidOperationException: IoC is not initialized.". Looking at the stack trace, its obvious that Caliburns ViewLocator is attempting to use IoC to create an instance of the view, but the IoC container is not initialized at design time.

So, the question is: How do you initialize Caliburn's IoC at design time?

EDIT:

Here is my UserControl declaration:

<UserControl x:Class="MyNamespace.Views.Checklist.ChecklistQuestionEditView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         xmlns:vm="clr-namespace:MyNamespace.ViewModels.Checklist"
         xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro.Platform"
         d:DataContext="{d:DesignInstance Type=vm:ChecklistQuestionEditDesignerViewModel, IsDesignTimeCreatable=True}"
         cal:Bind.AtDesignTime="True"
         d:DesignHeight="700" d:DesignWidth="1000">

And here is the ContentControl that causes the issue:

<ContentControl IsTabStop="False" Grid.Row="2" Grid.Column="0" Margin="12" Name="TranslationView"/>

This control is populated by Caliburn's Name conventions via this property in the view model:

private ChecklistQuestionTranslationViewModel _TranslationView;
public ChecklistQuestionTranslationViewModel TranslationView
{
    get { return _TranslationView; }
    set
    {
        if (_TranslationView != value)
        {
            _TranslationView = value;
            NotifyOfPropertyChange(() => TranslationView);
        }
    }
}

If I remove the ContentControl line above from the XAML, all other designer functionality works as expected.

For some reason, you can't copy the exception message from the designer, so I am putting a screen shot here. You can see that Caliburn is attempting to use IoC to create an instance of the View. but I don't have 10 reputation, so I can't post my screenshot.

Joel
  • 33
  • 5
  • do you have anything setup for design time already? Code snippet helps. http://caliburnmicro.com/documentation/design-time – mvermef Feb 14 '15 at 00:19
  • Can you add an explicit call to StartDesignTime in your bootstrapper and see if it fails with an exception. – Nigel Sampson Feb 17 '15 at 20:14
  • I added a call to StartDesignTime in my Bootstrapper constructor - there were no design-time changes- the exception still occurs, and there are no exceptions at run-time. – Joel Feb 18 '15 at 20:02
  • I have similar issue and I noticed this happens when a ContentControl tries to display a plain `string` object. When it tries to display a complex object, usually there's `cannot find view for XYZ` displayed. But for `string`, it's either this crash, or rarely `cannot find view for string`. – quetzalcoatl Feb 23 '15 at 12:14
  • I had this issue as well. It was due to an exception in the custom bootstrapper in `Configure`. Since `Configure` threw an exception, the `IoC` was never initialized. If there is an exception in the `StartDesignTime` function, then IoC will probably not work. You end up debugging the XAML Designer `XDesProc` from another instance to find the exception. – Ryan May 22 '20 at 22:44

1 Answers1

2

You might want to have a look at this SO thread I recently asked (and answered): up to now is working great for us.

The main points of that approach are:

  1. Prepare a fake design-time version for each of your view-models, both the container/parent as well as the one mapped to the ContentControl of your view (the child).

  2. Each design-time version has the empty constructor, no external dependencies to be set. It must not rely on DI/IoC container at all.

  3. For every public property data-bound between view and original view-model, the design-time view-model should have a property with the same name ... not necessarily the same type.

    • This is the case of your child view-model mapped to the ContentControl: the real parent view-model has e.g. a property of type MyCommandBarViewModel, while the fake parent view-model has one of type MyDesignTimeCommandBarViewModel.
  4. This might be applied to a whole visual tree of view-models, the leaves being view-models that just show simple property types (strings, numbers, etc.)

In order to have the Designer and Caliburn.Micro work together to generate those design-time versions, you need to add the following on the root UI element (Window, UserControl, ...):

<Window 
  d:DataContext="{d:DesignInstance Type=fake:YourDesignTimeViewModel, IsDesignTimeCreatable=True}"
  cal:Bind.AtDesignTime="True">
Community
  • 1
  • 1
superjos
  • 12,189
  • 6
  • 89
  • 134