Style based on StaticResource previously defined is not found at runtime
Asked Answered
D

1

9

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.

Durtschi answered 20/8, 2013 at 13:59 Comment(7)
I think TelerikCustomizations.xaml is not able to find RadRibbonViewStyle in BasedOn="{StaticResource ResourceKey=RadRibbonViewStyle}"Lonergan
Yeah, but why? Themes/Windows8/Telerik.Windows.Controls.RibbonView.xaml gets merged in right before TelerikCustomizations.xaml.Durtschi
Aren't you missing Themes from the source of first resource dictionary?Dolerite
@RohitVats no, because the dictionary is in the Themes folder. And I think that would generate a compile time error, not a runtime exception.Durtschi
You can try with DynamicResource : BasedOn="{DynamicResource ResourceKey=RadRibbonViewStyle}" Or you can merge RibbonView.xaml not directly the app.xaml or your merged dictionary but in your TelerikCustomizations.xaml and in your app.xaml only refernce TelerikCustomizations.xaml. So the point is that TelerikCustomizations.xaml and RibbonView.xaml should not be "next" to each other in a MergedDictionaries. But your customizations should depend on the ribbon.Selfexamination
@colinsmith Does not seem to work. Added a style without a key to App.xaml and the dictionary where everything gets merged together. still the same exception.Durtschi
@Selfexamination Merging the Telerik dictionaries in TelerikCustomizations.xaml works. I still want to know why though ;)Durtschi
S
9

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.

Selfexamination answered 20/8, 2013 at 15:0 Comment(2)
So in theory that would also work if you include Windows8/Telerik.Windows.Controls.RibbonView.xaml in your App.xaml before the MyTheme.xaml but I'm not sure in that. From the documentation it is not clear whether StaticResource is not working for direct "sister dictionaries" or it is also not working between "sister dictionary branches"...Selfexamination
Thank you very much, this explains a lot ;)Durtschi

© 2022 - 2024 — McMap. All rights reserved.