views:

506

answers:

2

This question involves the Visual Studio (2008) WPF Designer's apparent inability to handle the usage of resources located at the App.xaml level if the App.xaml is in a separate assembly from the view.

To simplify the explanation of the problem I have created a test application. This application has two assemblies: View and Start. The View assembly contains a xaml window called Window1, and the Start assembly includes the App.xaml file. The App.xaml file in the Start assembly has its StartupUri set to the Window1 in the View assembly. Neither of these files have code-behinds (aside from the standard constructors and InitializeComponent() call).

The code for this example is as follows:

App.xaml:

<Application x:Class="Start.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         StartupUri="pack://application:,,,/View;component/Window1.xaml"
         >
<Application.Resources> 

    <!-- Warning Text Style -->
    <Style x:Key="WarningTextStyle" TargetType="TextBlock">
        <Setter Property="FontWeight" Value="Bold" />
    </Style>

</Application.Resources>

Window1.xaml:

<Window x:Class="View.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" 
    Height="300" 
    Width="300"
    >

    <Grid>
        <TextBlock Text="This is test text" Style="{StaticResource WarningTextStyle}" />
    </Grid>
</Window>

The Window1.xaml file contains a single TextBlock that references the App-level WarningTextStyle. This code works fine at runtime because the Window properly finds the App-level resource; however, at design-time the designer complains that it cannot find the WarningTextStyle.

Does anybody know of a clean and scalable solution to this problem?

My standard approach with large applications is to organize my app-level resources into resource dictionary files, and then merge those dictionaries in the App.xaml. To work around the problem that I've described above I have to merge those resource dictionaries into each view's resources. This seems very inefficient, and if I later add another resource dictionary then I need to merge that new dictionary into every view.

A silver bullet solution would re-direct the designer to find the app-level resources. A reasonable work around would be the merging of the app-level resource dictionaries into each view, but only at design-time. At runtime I would like to avoid merging these dictionaries in every view because of the efficiency issues.

I've tried merging the dictionaries on each view in the view's code-behind constructor, and then wrapping that logic in an if statement that checks the DesignerProperties.GetIsInDesignMode() method; however, the Visual Studio designer does not run the view's constructor - so this approach appears to be a bust.

Does anybody have a better solution or work around?

+1  A: 

Can you merge the resource dictionary in your referenced assembly (be it App.xaml or your own resource dictionary) from your main (exe) assembly's App.xaml?

Rob Fonseca-Ensor
Rob, if I understand your question correctly you are suggesting that I merge my dictionaries into a single dictionary? That's a nice improvement over my current workaround because it removes the need to directly merge each dictionary on each view. Using that approach I can create a single resource dictionary (called ResourceRepository) that merges all of my resources. Then each view would merge the ResourceRepository dictionary instead of each of my specific resource dictionaries. However, I think the overhead of merging on each view is still a concern. What is the overhead of a merge?
Tony Borres
I'm merging a 200 key (when you add all the sub merges up) dictionary into doing it on about 20 (screen sized) user controls. Not seeing any issues at all. Premature optimisation and all that.
Rob Fonseca-Ensor
+1  A: 

I just had a different idea: use a DynamicResource instead of a Static one. This might introduce a tiny performance hit, but I doubt it would be measurable.

Rob Fonseca-Ensor
You're right, that would prevent the designer from breaking; however, the designer would not display the view as it appears at runtime. For simplified development I would prefer to have the designer accurately reflect the runtime view. Good suggestion though.
Tony Borres