ItemsControl, ViewModels & Value does not fall within the expected range.

Jul 12, 2010 at 3:05 PM
Edited Jul 12, 2010 at 3:11 PM

I am getting a very strange error in the caliburn micro framework and I have no idea what I am doing wrong. The only related post I could find was this but I could not extract a solution from it:

http://caliburn.codeplex.com/Thread/View.aspx?ThreadId=211660

Here is the code that I am sure you are familiar with. It follows your conventions:

//In my xaml I have...
<ItemsControl x:Name="Statuses" />

//In my ViewModel I have...
public BindableCollection<StatusBarEntryViewModel> Statuses { get; private set;}
public void Handle(IEvent message)
{                        
    Statuses.Add(new StatusBarEntryViewModel{Event = message});            
}

The first Add works perfectly, but the second add gives the following exception in Caliburn.Micro.View.cs on the red line:

private static void SetContentProperty(object targetLocation, object view)
{
    var type = targetLocation.GetType();
    var contentProperty = type.GetAttributes<ContentPropertyAttribute>(true)
                .FirstOrDefault() ?? new ContentPropertyAttribute("Content");

    type.GetProperty(contentProperty.Name)
                .SetValue(targetLocation, view, null);
}

The exception message I get deep within reflection: "Value does not fall within the expected range."

I have poked around a bit but this stuff is completely out of my league.

Coordinator
Jul 12, 2010 at 3:23 PM
Can you put together a simple VS solution and email it to me? That would greatly help me get the fix in quickly. Send it to: robertheisenberg at hotmail dot com Thanks!
Jul 12, 2010 at 4:53 PM

I quickly made a simple solution with the same conceptual functionality and the error does not seem to occur. 

I will have to introduce the additional elements I left out(such as MEF) to see when it starts to happen.

Will mail you as soon as I get it reproduced.

Coordinator
Jul 12, 2010 at 5:15 PM
Thanks! I'll be on the lookout for it.
Jul 13, 2010 at 10:32 AM
Edited Jul 13, 2010 at 10:34 AM

Ok I have figued out what the problem is.

Inside the ViewLocator there is a function called LocateForModelType. It does some work and at the end it calles GetOrCreateViewType. Inside GetOrCreateViewType something strange happens.

GetOrCreateViewType starts off by making a call to the IoC container with a call GetAllInstances. Now, the default behaviour implements that function inside the bootstrapper by just instantiating the type. However, in your post where you customized the bootstrapper for MEF that GetAllInstances function is overwritten to implement MEF's GetExportedValues which does not instantiate types at all, but rather returns already instantiated objects of that type. This causes views that were already instantiated by MEF to be served up again for view/model hookup which causes strange errors later on. I am guessing that when such a view is served up again and inserted into another ContentControl it fails deep inside .net with that beautifully descriptive error because the view already has a parent.

Jan 27, 2011 at 7:26 PM
pompomJuice wrote:

Ok I have figued out what the problem is.

Inside the ViewLocator there is a function called LocateForModelType. It does some work and at the end it calles GetOrCreateViewType. Inside GetOrCreateViewType something strange happens.

GetOrCreateViewType starts off by making a call to the IoC container with a call GetAllInstances. Now, the default behaviour implements that function inside the bootstrapper by just instantiating the type. However, in your post where you customized the bootstrapper for MEF that GetAllInstances function is overwritten to implement MEF's GetExportedValues which does not instantiate types at all, but rather returns already instantiated objects of that type. This causes views that were already instantiated by MEF to be served up again for view/model hookup which causes strange errors later on. I am guessing that when such a view is served up again and inserted into another ContentControl it fails deep inside .net with that beautifully descriptive error because the view already has a parent.

I have the same issue. How did you resolve it?

Jan 27, 2011 at 7:37 PM

haha, reading it now I cant believe what a noob I was.

The problem is simple, and not part of, or caused by Caliburn.Micro at all.

The problem is caused by the default part creation policy of MEF. That is why it kept on serving up the same instance.

Just add the following line below your [Export]s.

[PartCreationPolicy(System.ComponentModel.Composition.CreationPolicy.NonShared]