I've searched now for a while and found no solution for specific problem.
At first I've developed a WPF-Application with several Projects and UserControls using the same ResourceDictionary in more than 1 of the Projects. So I sourced the Resource dictionary out in a single Project only holding the dictionary.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFGlobalResources;assembly=WPFGlobalResources"
>
<!--Here are placed some styles I use globally -->
</ResourceDictionary>
In many of my Windows and UserControls I referenced WPFGlobalResources inside the Project and added
<Window.Resources> or UserControl.Resources
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/WPFGlobalResources;component/GlobalWpfResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
in the beginning of the xamls.
As long as I am working with an executable application everything just works fine and all resources can be loaded.
Now I needed a runnable Dll-Version of this Application to register it in Windows Registry. To do this, I threw the App.xaml out of my Project and turned it into a classlibrary, as I could found it described in many Google sites.
Registered there I can call it out of a CAD-Program - in this program it uses the call DLL MainApplication.exec 1
, which needs the following methods in my DLL-Project to get a new EntryPoint(I used a extra class for it):
public class Exec
{
public short vcExtStartUp(ref string Directory, string ExtensionName)
{ //I don't use this method
return 1;
}
public short vcExtMenuExec(ref int MenuID)
{ //this is what I need to run a WPF Application
Application app = new Application();
app.StartupUri = new System.Uri("MainWindow.xaml", System.UriKind.Relative); ;
app.Run(new MainWindow());
return 1;
}
}
Here I only need the second method, as you can see. My original Project threw some errors here so I reduced my Problem as much as I can, using only the Project containing the WPFGlobalResources and one Project containing an almost empty MainWindow containing a button, using a style from the dictionary, and a reference to the Project of my dictionary.
As long as I comment out the call of the mergedDictionary in the beginning of the MainWindow.xaml, everything works fine (of course I don't have the buttonstyle then). If I try to use the ResourceDictionary, my CAD-Program crashes while calling the DLL and debugger leads me to the error: (Hope I translated it correctly)
IOException - Additional Information: Assembly.GetEntryAssembly() returns NULL. Define Application.ResourceAssembly-Property or use the Syntax "pack://application:,,,/assemblyname;component/" to define the assembly the resource should be loaded from.
Ok, then I've added Application.ResourceAssembly = typeof(MainWindow).Assembly;
just behind new Application(). Now the Debugger gets a little bit more forward, but stopping again with the error:
Exception in MainWindow.xaml linenumer12 ... -> InnerException {"File or Assembly "WPFGlobalResources, Culture=neutral" or a dependency of it couldn't be found. System can't find specified file.":"WPFGlobalResources, Culture=neutral"} System.Exception {System.IO.FileNotFoundException}
I've also tried to add
System.Uri resourceLocater = new System.Uri("/MainApplication;component/VisiDockedMainWindow.xaml", System.UriKind.Relative);
System.Windows.Application.LoadComponent(resourceLocater);
but with no success, still the same error.
Now I can't find a solution to make it work. Is it possible that pack://application... now targets my CAD-Program as application and not the Location of my DLL, where the WPFGlobalResources.dll (and every other dll) is located? And how can I change that, I couldn't find a URI for this usecase in MSDN.
Next thing I have to try is dumping my WPFGlobalResources and adding the styles to every single Window/Usercontrol, but I hope that is not the only solution??? Produces a lot of redundant code...
Okay, after trying alot I meanwhile found a solution:
The point is, that while executing the xaml-Code of the MainWindow, references seem not to be loaded. The solution is simply adding a:
Assembly resAssembly = Assembly.Load("WPFGlobalResources");
before using app.Run. This seems to preload the external reference and then it can be found.
Interesting hint: In this case it is even better to leave the WPF-Application without any changes (still executable with App.xaml stuff) and add an extra Classlibrary-Project to create the dll. And then you can add a class starting your WPF-Application (of course you have to reference the WPF-Projekt and the ResourceDictionary-Projekt first):
public class Exec
{
public short vcExtStartUp(ref string Directory, string ExtensionName)
{
return 1;
}
public short vcExtMenuExec(ref int MenuID)
{
Thread thread = new Thread(() =>
{
WpfTestAppl.App app = new WpfTestAppl.App();
// Loading of ResourceAssemblys
Assembly resAssembly = Assembly.Load("WPFGlobalResources");
app.Run(new WpfTestAppl.MainWindow());
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return 1;
}
}
And now it finally works :-)