Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Style based on StaticResource previously defined is not found at runtime

I'm using Telerik's RadControls for WPF with implicit styling. The following style is defined in Themes/Windows8/Telerik.Windows.Controls.RibbonView.xaml:

<Style TargetType="telerikRibbonView:RadRibbonView" x:Key="RadRibbonViewStyle">
...
</Style>

My own styles and the Telerik default ones get merged like this in the assembly Lib.Windows.Controls in the folder Themes:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Windows8/Telerik.Windows.Controls.RibbonView.xaml" />        
        <ResourceDictionary Source="MyTheme/TelerikCustomizations.xaml" />

        <ResourceDictionary>
            <!-- avoid optimization -->
            <Style TargetType="{x:Type Rectangle}" />
        </ResourceDictionary>
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

And in TelerikCustomizations.xaml I define the following (empty, for testing purposes) style:

<Style x:Key="MyThemeRadRibbonViewStyle" TargetType="{x:Type telerik:RadRibbonView}" BasedOn="{StaticResource ResourceKey=RadRibbonViewStyle}" />

Which results in the following exception at runtime:

'Provide value on 'System.Windows.Markup.StaticResourceHolder' threw an exception.' Line number '4' and line position '42'. {"Cannot find resource named 'RadRibbonViewStyle'. Resource names are case sensitive."}

Which led me to the following debugging statements in MyView.xaml.cs:

public ShellView()
{
    var baseStyle = FindResource("RadRibbonViewStyle");
    var inherited = FindResource("MyThemeRadRibbonViewStyle");
    InitializeComponent();
}

Now the thing is: The exception is thrown on the second FindResource call. With the exact same message. However the RadRibbonViewStyle is clearly found in the first line of the constructor.

If it matters, the merged dictionary is actually merged in App.xaml a second time.

I'm sure I'm missing something obvious, but I can't figure out what.

App.xaml

<Application x:Class="TestClient.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="Views/ShellView.xaml">
    <Application.Resources>
      <ResourceDictionary>
          <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/Lib.Windows.Controls;component/Themes/MyTheme.xaml" />

              <ResourceDictionary>
                    <!-- added to avoid optimization -->
                    <Style TargetType="{x:Type Rectangle}" />
                </ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
      </ResourceDictionary>
    </Application.Resources>
</Application>

App.xaml.cs does not overwrite the constructor. In fact it does not do anything.

Update

If I merge the Telerik dictionaries in TelerikCustomizations.xaml instead of merging them in yet another dictionary (MyTheme.xaml), the exception disappears.

However, I'd still like to know why this happens.

like image 893
cguedel Avatar asked Aug 20 '13 13:08

cguedel


1 Answers

You need to merge in the Windows8/Telerik.Windows.Controls.RibbonView.xaml in your MyTheme/TelerikCustomizations.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Windows8/Telerik.Windows.Controls.RibbonView.xaml" />
        <ResourceDictionary>
            <Style x:Key="MyThemeRadRibbonViewStyle" TargetType="{x:Type telerik:RadRibbonView}" BasedOn="{StaticResource ResourceKey=RadRibbonViewStyle}" />
        </ResourceDictionary>
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

And now you can use/merge this dictionary wherever you want.

You need to do this because StaticResource is not working between "sister" MergedDictionaries so you cannot reference a resource which was merged on the same level because the StaticResource looks only backwards to the direct parents:

From MSDN:

XAML resource references within a particular resource dictionary must reference a resource that has already been defined with a key, and that resource must appear lexically before the resource reference. Forward references cannot be resolved by a XAML resource reference

But when using MergedDictionaries:

In the resource-lookup sequence, a MergedDictionaries dictionary is checked only after a check of all the keyed resources of the ResourceDictionary that declared MergedDictionaries.

like image 100
nemesv Avatar answered Jan 16 '23 01:01

nemesv