views:

240

answers:

1

I need to instantiate WPF types (say, a UserControl or a Page) via reflection for a designer. The problem I'm having is that when I attempt to instantiate these using Activator.CreateInstance I get a TargetInvocationException which wraps, in the end, an exception thrown by the StaticResource markup extension.

Clarification: The types are in a different assembly that is loaded at runtime!

Apparently, Activator.CreateInstance can't instantiate types that use the {StaticResource XXX} markup extension, even when the static resource is defined in the type's definition.

So, if all you have is the following type's definition (Type + xaml file):

<Page x:Class="Hurr.Durr">
  <Page.Resources>
    <ControlTemplate x:Key="whatever">
      <TextBlock Text="This is a stupid example."/>
    </ControlTemplate>
  </Page.Resources>
  <ContentControl Template="{StaticResource whatever}" />
</Page>

How would you spin this up at runtime?

BTW, requiring that you use DynamicResource instead is not acceptable. Does Visual Studio require this? Yet VS is able to spin up a copy of your WPF framework element and stick it in the designer.


Here's a sample application (beta 2, sorry) that demonstrates the issue.

http://cid-f8be9de57b85cc35.skydrive.live.com/self.aspx/Public/ResourcesGoKaboom.zip

The app attempts to load a Page with a drawing in its resource dictionary. I try to load it dynamically using Application.LoadComponent and Activator.CreateInstance and they both fail.


Okay, the example above works without an issue. The issue was that I was using a StaticResource within an element's attributes that referenced a resource defined within that element.

What was throwing me was that this works within visual studio. So in the designer everything looked okey dokey but IRL it was all pear shaped. IMHO, this is a bug and I've reported it as such:

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=519244

Not sure if its a failure of VS to.... fail, or if the StaticResource extension was working in VS but not IRL.

+1  A: 

The problem appears to be with the Page you're trying to load. Your Page looks like this (omitting a bunch of xmlns etc. plumbing):

<AwesomePage Title="AwesomePage" Background="{StaticResource awesomeface}">
    <AwesomePage.Resources>
        <DrawingBrush x:Key="awesomeface" Stretch="Uniform">
            <!-- details snipped -->
        </DrawingBrush>
    </AwesomePage.Resources>
</AwesomePage>

This tries to use the awesomeface resource before it is defined. StaticResource does not allow this kind of forward referencing: therefore the StaticResourceExtension.ProvideValue fails and you get the error you have run into.

To fix this, put a Border immediately inside the Page, and move the Background setter from the Page to the Border. Then put all your content inside the Border.

itowlson
Hmmmmm........ It works in VS, however it doesn't work *outside of VS*. Let me check some more on this...
Will
Okay, that works. The thing that was screwing me up was that it WORKED in visual studio, but it does NOT WORK when the application runs. This, imho, is a bug.
Will