Trouble referencing a Resource Dictionary that contains a Merged Dictionary

前端 未结 5 587
野性不改
野性不改 2020-11-27 14:41

I have a library, CommonLibraryWpfThemes, with several Resource Dictionary XAML files in it. My Themes/Generic.xml file contains a ResourceDictionary.MergedDictionaries decl

相关标签:
5条回答
  • 2020-11-27 14:59

    My solution is here, click Workarounds.

    0 讨论(0)
  • 2020-11-27 15:01

    Check your constructor in App.xaml.cs calls InitializeComponent() - this is what merges the resource dictionaries...

    0 讨论(0)
  • 2020-11-27 15:12

    You should not have to reference generic.xaml at all, it has built-in support. This however means that it provides default styling, which you do not set explicitly. Explicitly set styles/templates need to be attainable from explicitly referenced res dictionaries.

    (EDIT for clarity)

    One exception to this is the App.xaml, where defined resources become accessible by the whole app, without requiring to reference any specific resource dictionary. The resource itself, would have to be accessible by name.

    The reason why this fails

    <Application.Resources>
        <ResourceDictionary
            Source="/CommonLibraryWpfThemes;component/Themes/Generic.xaml" />
    </Application.Resources>
    

    is, I think, because you didn't wrap it in a MergedDictionary wrapper, adding it to merged dictionaries. Adding directly to resources works only for resources you declare locally, e.g. the styles, etc. themselves.

    However, as I said before, you shouldn't have to merge generic.xaml anywhere, maybe you should just refactor brushes and other resources used outside styles, and merge only those resources in app.xaml.

    Also note that styles do not have to be in generic.xaml to have "default style" behaviour - if a style with key equal to the type of the element is accessible to it (globally, or in local resources), then it will use the style as a default style. The generic.xaml is just a convenience.

    Check this answer.

    For other custom brushes, etc, you need to reference those resources explicitly.

    You should also check the contents of the WindowDictionary.xaml, this error has a certain smell about it.

    0 讨论(0)
  • 2020-11-27 15:13

    Answered a similar question here earlier, see Adding a Merged Dictionary to a Merged Dictionary question.

    This is an optimization bug, see Microsoft Connect / DefaultStyleKey style not found in inner MergedDictionaries:

    On the creation of every object in XAML, if a default style is present (i.e. style w/ a key of Type) that style should be applied. As you can imagine there are several performance optimizations to make that (implied) lookup a light weight as possible. One of them is that we don’t look inside Resource Dictionaries unless they are flagged as “containing default Styles”. There is a bug: if all your default styles are nested in merged dictionaries three levels deep (or deeper) the top dictionary does not get flagged so the search skips it. The work around is to put a default Style to something, anything, in the root Dictionary.

    So adding a dummy style to the root dictionary fixes this. Example

    <Application x:Class="MyApp.App"  
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">  
        <Application.Resources> 
            <ResourceDictionary> 
                <ResourceDictionary.MergedDictionaries> 
                    <ResourceDictionary 
                        Source="/CommonLibraryWpfThemes;component/Themes/Generic.xaml" /> 
                    </ResourceDictionary.MergedDictionaries> 
                <!-- Dummy Style, anything you won't use goes --> 
                <Style TargetType="{x:Type Rectangle}" /> 
            </ResourceDictionary> 
        </Application.Resources> 
    </Application>   
    
    0 讨论(0)
  • 2020-11-27 15:20

    I was getting this error in my unit tests and Chris' answer from above gave me the clue I needed. Basically on my first tested method, I put:

            MyApplication.App app = new MyApplication.App();
            app.InitializeComponent();
    

    And suddenly it could find my template for my pages. Note: this does mean that you have to check to see if an instance of your App already exists if you are unit testing your App.cs as well.

    0 讨论(0)
提交回复
热议问题