Even a chimp can write code

Thursday, April 15, 2010

Can you access a loose XAML file from LoadComponent?

The answer is no. The job of Application.LoadComponent in Silverlight is to “merge” a specified XAML file with a specified object.

public void Application.LoadComponent(object, Uri);

In doing so, it does a series of validations:

  • checks that neither parameter is null
  • checks whether the specified XAML URI is absolute or relative. Absolute URIs are not allowed.
  • checks whether the specified XAML is embedded within an assembly. If not, LoadComponent fails.
  • checks whether the root element declared in the specified XAML is actually the same type as that of the specified object. If not, LoadComponent fails.

and only then attempts to merge the two in a custom parsing step.

Well, why not?

The last bullet point above is consequential in why we don’t allow loose XAML. LoadComponent thinks of an assembly as a logical boundary. In the presence of XAML with contents like this:

<UserControl x:Class=”Foo”> …

the only unambiguous way for Silverlight to identify and locate “Foo” is if it knew the DLL where that type was defined. Iterating through all DLLs loaded in the AppDomain isn’t an optimal solution at all. This is why it insists that the XAML be embedded within a DLL. Then it knows the un-qualified type is defined within that DLL. In practice, the URI specified on the LoadComponent call ends up being something like:

/SomeAssemblyName;component/Page.xaml

which has metadata on the provenance of said XAML i.e. that it came from an assembly with short name “SomeAssemblyName”. Silverlight can now happily match it against the type backing the other specified parameter – the object.

How does one work around this?

A workaround exists, but it has some limitations. You can use XamlReader.Load() to have Silverlight create an object tree from your specified markup. The caveat being that said XAML cannot have code-behind associations i.e. a backing type as root element, or event handler declarations. This approach is ideal if you’re dealing with sprites that are injected into the app, with other plumbing hooked up programmatically.

Aside: This is part of a recycling bits series I've been considering for a while. I frequently find myself answering the same questions over email or other forums, and figure I'd give some of those FAQs airtime on this blog, so as to multiply any benefits the information might have.

Labels:

Email this | Bookmark this

1 Comments:

  • I'm working on Silverlight port of a framework I wrote for WPF that allows for Loose XAML to have event handlers as well as routed commands and data binding (both via Dependency Properties and INotifyPropertyChanged).

    If interested, check out: http://xtrememvvm.codeplex.com/

    - Clay

    By Anonymous Anonymous, at August 1, 2011 at 9:24 AM  

Post a Comment | Home | Inference: my personal blog