views:

94

answers:

1

I have a user control UserControl which is in an assembly Assembly. I have a WPF application which instantiates UserControl in a programmatic way. I have already added a reference to Assembly. However, during runtime I get the ff. exception:

Cannot locate resource 'usercontrol.xaml'.
   at MS.Internal.AppModel.ResourcePart.GetStreamCore(FileMode mode, FileAccess access)
   at System.IO.Packaging.PackagePart.GetStream(FileMode mode, FileAccess access)
   at System.IO.Packaging.PackagePart.GetStream()
   at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
   ...

I changed the build action for UserControl.xaml to EmbeddedResource but this caused compilation problems so I put it back to the default Page setting. I have tried this in .NET 3 and 4 to no avail. Anyone have any idea?

+2  A: 

The most common cause of this is if you rename an assembly. I'll explain that scenario, then give some other possibilities.

Assume you have a DLL project "Abc" containing UserControl "MyControl". The generated InitializeComponent for MyControl in Abc.dll will contain the Uri "/Abc;Component/MyControl.xaml".

At runtime, the assembly name "Abc" is extracted and the loaded assemblies are searched for an assembly by that name. If such an assembly is found but it does not have a "MyControl.xaml" resource, you get the error you posted in the question.

So here is the scenario:

  • You rename the Abc.dll file to Def.dll
  • You (or someone) creates a different Abc.dll file
  • In your project you reference Def.dll (which was compiled as Abc.dll)
  • Your project also directly or indirectly references Abc.dll so it is loaded when MyControl is instantiated

Now when you instantiate MyControl from Def.dll, it looks for its xaml in the Abc.dll assembly instead of the Def.dll assembly.

Some other scenarios in which this can happen:

  • You have a stale .g.cs file in your obj directory that has the wrong name for the xaml file. This can happen if you changed the source code without updating the date (which can happen during a checkout from a source control system or an unzip of a zip file or many other ways). Cleaning and rebuilding the solution will fix this. Since your comment says you tried this, this does not apply to you.

  • You are manually editing resource names in the .dll file after it has been compiled

  • You have loaded two assemblies with the same name (yes, this is possible), and the resource loader found the wrong one

Note that any change to the path to the XAML file, such as renaming or moving it, can cause this problem if the .g.cs file doesn't match the path in the resources.

To diagnose your problem further I recommend you download a copy of NET Reflector and look at your .dll file to see:

  1. What Uri does the InitializeComponent() specify?
  2. Is there a .baml file with the same name?

You can also examine the call stack at the point where the exception is thrown to make sure the resource manager being used has a reference to the expected assembly, not some other assembly.

Ray Burns
Why is it looking for the XAML though? I thought the XAML is needed only to derive the g.cs file.
Chry Cheng
Rebuilding seems to have done the trick. I created a new build to test out your answer and have not encountered it again. I know I said I already tried this and I'm really sure I did.
Chry Cheng
To answer your question: When you build your project, your .xaml file gets converted into two files: a .g.cs file and a .baml file. The C# compiler compiles the .g.cs file to IL and includes it in your assembly. The .baml is added to your assembly as a resource. In the .g.cs file, the path to the .baml file is listed but it has the extension ".xaml". Application.LoadComponent has some internal logic that replaces the ".xaml" extension with ".baml" before searching the resources in the assembly. Thus, you have IL (code) that specifies ".xaml" but the resource itself has extension ".baml".
Ray Burns