Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to Define Common Resources Across WPF Applications (including templates)?
    primarykey
    data
    text
    <p>I am looking for a way to define a WPF resource (for now, to be used as a static resource) that is accessible from everywhere within my application.</p> <p>My resource is defined in this resource dictionary:</p> <pre><code>&lt;ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&gt; &lt;Style x:Key="flatButtonStyle" BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" TargetType="{x:Type Button}"&gt; &lt;Setter Property="BorderThickness" Value="4"/&gt; &lt;/Style&gt; &lt;/ResourceDictionary&gt; </code></pre> <p>The selected answer to <a href="https://stackoverflow.com/questions/703026/shared-resource-dictionary-between-several-user-controls-and-across-assemblies/705061">this question</a> indicates that I must merge that resource dictionary into my <code>App.xaml</code> file (of a project called <code>AppWideResources</code>):</p> <pre><code>&lt;Application x:Class="AppWideResources.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="Window1.xaml"&gt; &lt;Application.Resources&gt; &lt;ResourceDictionary&gt; &lt;ResourceDictionary.MergedDictionaries&gt; &lt;ResourceDictionary Source="/AppWideResources;component/CommonResources.xaml"/&gt; &lt;/ResourceDictionary.MergedDictionaries&gt; &lt;/ResourceDictionary&gt; &lt;/Application.Resources&gt; &lt;/Application&gt; </code></pre> <p>At first, this seems to work; the button in this window is appropriately styled in a flat way with an extra-thick border:</p> <pre><code>&lt;Window x:Class="AppWideResources.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="AppWideResources" Height="300" Width="300" &gt; &lt;StackPanel&gt; &lt;Button Style="{StaticResource flatButtonStyle}" Content="Test" HorizontalAlignment="Stretch"/&gt; &lt;/StackPanel&gt; &lt;/Window&gt; </code></pre> <p><strong>However</strong>, this stops working as soon as I use my shared resource in a control template:</p> <p>My (extremely simplified, for the purpose of this question) control:</p> <pre><code>using System; using System.Windows; using System.Windows.Controls; namespace AppWideResources { public class MyControl : Control { static MyControl() { DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(typeof(MyControl))); } } } </code></pre> <p>... and the corresponding <code>Themes\Generic.xaml</code> file:</p> <pre><code>&lt;ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:AppWideResources"&gt; &lt;Style TargetType="local:MyControl"&gt; &lt;Setter Property="Template"&gt; &lt;Setter.Value&gt; &lt;ControlTemplate TargetType="local:MyControl"&gt; &lt;StackPanel Orientation="Horizontal"&gt; &lt;Button Style="{StaticResource flatButtonStyle}" Content="1"/&gt; &lt;Button Style="{StaticResource flatButtonStyle}" Content="2"/&gt; &lt;/StackPanel&gt; &lt;/ControlTemplate&gt; &lt;/Setter.Value&gt; &lt;/Setter&gt; &lt;/Style&gt; &lt;/ResourceDictionary&gt; </code></pre> <p>This control is then inserted into my window:</p> <pre><code>&lt;Window x:Class="AppWideResources.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:AppWideResources" Title="AppWideResources" Height="300" Width="300" &gt; &lt;StackPanel&gt; &lt;Button Style="{StaticResource flatButtonStyle}" Content="Test" HorizontalAlignment="Stretch"/&gt; &lt;local:MyControl/&gt; &lt;/StackPanel&gt; &lt;/Window&gt; </code></pre> <p>If I run this, a <a href="http://msdn.microsoft.com/en-us/library/system.windows.markup.xamlparseexception%28v=vs.110%29.aspx" rel="nofollow noreferrer"><code>XamlParseException</code></a> is thrown, saying that the static resource <code>flatButtonStyle</code> cannot be found.</p> <p>The only workaround I have found is by explicitly merging the common resource dictionary into the local resource dictionary of the control template:</p> <pre><code>&lt;ControlTemplate TargetType="local:MyControl"&gt; &lt;ControlTemplate.Resources&gt; &lt;ResourceDictionary&gt; &lt;ResourceDictionary.MergedDictionaries&gt; &lt;ResourceDictionary Source="/AppWideResources;component/CommonResources.xaml"/&gt; &lt;/ResourceDictionary.MergedDictionaries&gt; &lt;/ResourceDictionary&gt; &lt;/ControlTemplate.Resources&gt; &lt;StackPanel Orientation="Horizontal"&gt; &lt;Button Style="{StaticResource flatButtonStyle}" Content="1"/&gt; &lt;Button Style="{StaticResource flatButtonStyle}" Content="2"/&gt; &lt;/StackPanel&gt; &lt;/ControlTemplate&gt; </code></pre> <p>However, not only is this quite verbose and error-prone with several lines of redundant code (my actual project contains quite a few templated controls, not just one), I am also concerned about wasting system resources by loading the static resources several times (once for every time <code>CommonResources.xaml</code> is included). (Is that concern justified? Or does WPF use the same instances every time when loading a particular resource dictionary?)</p> <p>So, the question is: <strong>What is the proper way to make a WPF resource accessible throughout the whole application, including control templates?</strong></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload