Thursday, March 10, 2011

VS Designer can’t find Resource

We got bit by this one today.

We asked the App.xaml to create a ViewModelLocator as a resource.

<local:ViewModelLocator x:Key="Locator" />

Blend was fine with that. But the Visual Studio Designer (“Cider”) reported an error along the lines of “Cannot find key ‘Locator’” and “Cannot add type to ResourceDictionary”. Of course the view failed to show in the Cider designer. Not good.

We know ViewModelLocator type is defined in “local”. Blend could find it. Why not Cider? Utterly maddening.

We noticed that ViewModelLocator derived from a base class – call it ViewModelLocatorBase – which happed to be defined in a referenced assembly.

When we redefined the ViewModelLocator without the base class, Cider was happy. When we copied the base class into the same project as the ViewModelLocator and derived from the copy, Cider was happy.

There was nothing wrong with the base class itself.  Cider just wouldn’t find the derived class when it was located in a foreign assembly. We couldn’t get it to pay attention to the assembly reference. “Copy local = true” didn’t help.

Adding an xmlns reference to that foreign assembly in the App.xaml didn’t help either.

Solution: Give the referenced assembly an XmlnsDefinition

We stumbled into this workaround on a hunch. We opened the AssemblyInfo.cs of the project in which ViewModelLocatorBase is defined and added an Xmlns definition attribute … such as this one:

[assembly: XmlnsDefinition(http://schemas.ideablade.com/presentation, "IdeaBlade.Presentation")]

We recompiled the project and added this xmlns to the top of App.xaml.

xmlns:ibp="http://schemas.ideablade.com/presentation"

Cider smiled upon us at last.

We don’t know if this is the only way to recover. We just know that it works.

Notes:

  • Learn more about XmlnsDefinition here.
  • Remember to add a separate XmlnsDefinition for each namespace in that project.
  • You only encounter this problem when the resource class or one of its ancestors lives in a referenced assembly. It is ok if the resource needs something that resides in a referenced assembly.There’d be no problem if the ViewModelLocator created a Foo and Foo is defined in a separate assembly; Foo isn’t a resource. The problem arose because ViewModelLocator – which is a resource – depends upon the ViewModelLocatorBase class that resides in a separate referenced assembly.

1 comment:

Unknown said...

Nice discovery. This helped me fix several issues I had in Cider. Thanks!