Styles and modules

Topics: Prism v2 - WPF 3.5
Jan 21, 2010 at 7:48 AM

Hello! During reviewing quickstarts on PRISM, to be more precisely StockTrader app,  I'm faced the next problem: bootstrapper project with shell contains Application's resource dictionary, where all styles, including that ones that are used in other modules. Doing so leads that in design time designer couldn't display View, that use style from shell's module, while at run-time all works fine, as module loads to this root assembly with styles dictionary. Having centralized dictionary is convenient, but how to be in design time, how to see what you draw? Especially if UI is becoming complex.

Jan 21, 2010 at 10:19 AM
Edited Jan 21, 2010 at 10:35 AM

This is less of a Composite WPF problem and more of a designer problem, as this affects any WPF application once multiple assemblies are involved.

The approach I use for this is to split the styles and resources into a third assembly. So you might have:

  • MyApp
    • Bootstrapper
    • App.xaml
  • MyApp.Assets
    • ButtonStyles.xaml
    • TextBoxStyles.xaml
  • MyApp.FooModule
    • Views go here

The other two assemblies would register MyApp.Assets.

App.xaml would reference the resource dictionaries from the resources assembly:

     <ResourceDictionary Source="/MyApp.Assets;component/ButtonStyles.xaml" />
     <ResourceDictionary Source="/MyApp.Assets;component/TextBoxStyles.xaml" />

This way, the resources are available at run time.

At design time, in Expression Blend 3, this will just work. So long as your assemblies all reference the resources assembly, Blend will recognise the App.xaml file and import it, even though it lives in a different project. You can preview your views as expected, and even assign styles as defined in the external dictionaries.

However, unfortunately it doesn't work in Visual Studio 2008 at design time. It does however work in VS 2010.

My usual recommendation would be to just use Visual Studio for the intellisense and XAML editing and use Blend for previewing and any design work - it's just a brilliant tool. Or wait for 2010.

That said, if you really, really want designer support in VS 2008, you have two choices. The first and simplest is to import the resources for each view:

<UserControl ....>
              <ResourceDictionary Source="/MyApp.Assets;component/ButtonStyles.xaml" />

Aside from the duplication, the main problem with this is that it means each view re-loads the same set of resources. If your resource dictionaries include expensive resources like images, I've seen this balloon out to an application that uses 22mb every time you open a view. So it's best to avoid this.

The second approach is to create a base class for all views, and load the resources manually:

    public class View : UserControl
        public View()
            if (DesignerProperties.GetIsInDesignMode(this))
                Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("/MyApp.Assets;component/All.xaml", UriKind.Relative)});

This way at runtime the resources are only loaded once, and at design time they are available for your views.

This gives you designer support for Blend 3 and Visual Studio 2008, but it does add some complexity.