Managing application resources when WPF is hosted

Recently, I was working on a project that had WPF controls and windows hosted in Windows Media Player. When using WPF styles correctly (themes, resources, etc), normally one would create a resource library with all the styles.

When WPF is hosted, no System.Windows.Application.Current is available, so no application resources are available. Because of this, every window and control has to load the main theme resource dictionary on each load. This isn’t exactly what one would like to do. After searching for a while, I found this interesting article of Dr. WPF. It’s a long article, but the most interested part is to create the current application object yourself:

public static void EnsureApplicationResources()
{
    if (Application.Current == null)
    {
        // create the Application object
        new Application();

        // merge in your application resources
        Application.Current.Resources.MergedDictionaries.Add(
            Application.LoadComponent(
                new Uri("MyLibrary;component/Resources/MyResourceDictionary.xaml",
                UriKind.Relative)) as ResourceDictionary);
    }
}

At first, this seemed to work great in my scenario. However, when a window was shown the 2nd time, the application (in my case, Windows Media Player) crashed. After some investigation, I noticed that the application was not valid anymore after the the first window was shown. This brought me to the idea that the first window that is created is automatically set to the main window of the application. As soon as that window closes, the application gets destroyed. However, I don’t have a main window, I can only show windows as popups, not as main window of the application.

Hereby, I present to you as a reader of my blog, the solution to this issue. Create the first “main application window” yourself and make sure that it is invisible. This window will stay in scope (since Application.Current.MainWindow has a reference) as long as the hosting application is running. The following code should be used instead of the one that Dr. WPF has posted:

/// 
/// Ensures that an application instance exists and the styles are applied to the application.
/// 
public static void EnsureApplicationResources()
{
	// Do we have an application?
	if (Application.Current == null)
	{
		// Create the Application object
		new Application();

		// merge in your application resources
		Application.Current.Resources.MergedDictionaries.Add(Application.LoadComponent(new Uri("/MyLibrary;component/Themes/Generic.xaml", 
			UriKind.RelativeOrAbsolute)) as ResourceDictionary);

		// Create style forwarders
		CatenaLogic.Windows.StyleHelper.CreateStyleForwardersForDefaultStyles(Application.Current.Resources);

		// Create an invisible dummy window to make sure that this is the main window
		Window dummyMainWindow = new Window();
		dummyMainWindow.Visibility = Visibility.Hidden;
	}
}

As you might have noticed, a StyleHelper is used. This is another article, you can find it here.

kick it on DotNetKicks.com

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList