17

How can WPF resources - including styles, templates, etc. - be organized, so that I can use them across Windows, Pages or even Projects. What options do I have to achieve maximum re-usability of my resources and a maintainable structure (for example one file per Template)?

For example: I am creating a WPF application and I want to use a TabControl, but I want to make major changes to it. So I could create a style in and apply it to the TabControl and TabItem. That's ok, but where can I place my resources to keep my Window XAML clear and have the style accessible from other Windows or projects as well?

I found that I can add it to App.xaml but that is only a solution for one project and allows sharing just between items of this project. Also, I think it would be better to have these templates a little separate from other code, than placing it all in some page or app.xaml?

Marc
  • 12,706
  • 7
  • 61
  • 97
Libor Zapletal
  • 13,752
  • 20
  • 95
  • 182
  • You can create a ResourceDictionary and add it on an ClassLibrary. You have to reference it on your App.xaml and you can use the Library in many projects – Joffrey Kern Mar 06 '13 at 14:11

3 Answers3

42

I usually create a seperate styling project, which I reference from the projects, which I want to style. The styling project has a fixed structure like this:

Styling project

For every control, I create a styling ResourceDictionary. For example for my buttons:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style x:Key="PrimaryButtonStyle" TargetType="Button">
    </Style>

    <Style x:Key="ToolbarButton" TargetType="Button">
        <Setter Property="BorderThickness" Value="0" />
        <Setter Property="Margin" Value="3"/>
        <Setter Property="Background" Value="Transparent"></Setter>
    </Style>
</ResourceDictionary>

In one main ResourceDictionary, I merge all the other dictionaries, in this case in the file IncaDesign.xaml, which you can see in the picture above:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:controls="clr-namespace:Commons.Controls;assembly=Commons">

    <ResourceDictionary.MergedDictionaries>

        <ResourceDictionary Source="Converter/Converter.xaml" />
        <ResourceDictionary Source="Styles/Button.xaml" />
        <ResourceDictionary Source="BitmapGraphics/Icons.xaml" />

    </ResourceDictionary.MergedDictionaries>

    <!-- Default Styles -->
    <Style TargetType="Button" BasedOn="{StaticResource PrimaryButtonStyle}"></Style>
</ResourceDictionary>

Notice how I defined the default styles, which are applied automatically, unless you specify otherwise. In every window or control, that you want to style, you only need to reference this one ResourceDictionary. Note the definition of the source, which is a reference to the assembly (/Commons.Styling;component...)

<UserControl.Resources>        
    <ResourceDictionary>            
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Commons.Styling;component/IncaDesign.xaml" />
        </ResourceDictionary.MergedDictionaries>   
    </ResourceDictionary>        
</UserControl.Resources>

Default styles will be set automatically now, and if you want to access a resource explicitly, you can do this, using StaticResource.

<Viewbox Height="16" Width="16" Margin="0,0,10,0">
    <ContentControl Content="{StaticResource FileIcon32}" />
</Viewbox>

This is very nice solution in my opinion, which works for very complex solutions, including modular solutions, for example built with PRISM.

Marc
  • 12,706
  • 7
  • 61
  • 97
  • Keep in mind that ResourceDictionary instances are resource heavy and you are better off avoiding them if possible. [See VI.](http://pelebyte.net/blog/2011/07/11/twelve-ways-to-improve-wpf-performance/) – Nathan Hillyer Mar 06 '13 at 14:26
  • 3
    The most important thing is to avoid cross references and unsystematic merging of dictionaries. This is what really causes trouble, as you create duplicates of all your resources all the time, not the ResourceDictionary itself. I think this is the point, the article you've linked is referring to. I don't see a way of avoiding ResourceDictionaries in a complex project... And this is exactly the idea of the styling project: To avoid merging dictionaries in many places... – Marc Mar 06 '13 at 14:31
  • Exactly what I was looking for :) Thank you. I just must read more about that possible problems with this. – Libor Zapletal Mar 06 '13 at 15:41
  • This is an old question/answer but what project type do you use for your common project? – WBuck Jan 09 '19 at 01:22
  • @WBuck Its a class library. Just add the required references to PresentationCore, PresentationFramework,System.Xaml,WindowsBase and it should work well. – Marc Feb 21 '19 at 11:15
  • I partly agree with Nathan. As Marc described, ResourceDictionary do (nothing but) organizing your xaml into different files. Referencing all relevant ResourceDictionaries in your App.xaml makes them globally available for all Windows and UserControls. In a UserControl -> adding a reference to a ResourceDictionary that is already referenced in App.xaml creates new instances with every UserControl instance. This is resource heavy and not required. Working with modular architectures like PRISM the WPF designer might require such a reference, but not at application runtime. – sa.he Apr 09 '19 at 09:32
  • And how use resources from Colors/colors.xaml into others xaml like Button.xaml for example ? – xNiux Aug 23 '23 at 10:26
  • Ok, I found solution, it just add to source the color file like that : – xNiux Aug 24 '23 at 09:15
  • This seems to be very good solution ! But how integrate the styling in an app ? I add my styling project to the reference and add followings lines to my app.xaml... It's ok in conceptor, but it crash at execution ... – xNiux Aug 24 '23 at 09:21
1

A ResourceDictionary is for what you are looking.

Here is an explanation for how to use them within and across projects.

Nathan Hillyer
  • 1,959
  • 1
  • 18
  • 22
1

You can create a project that contains Resource Dictionaries, either in your solution or in a separate one. Your project will be a Class Library type and can then easily be .dll referenced from any other project. Here is an article describing this: Resource Dictionary Article