Проблема со ссылкой на словарь ресурсов, который содержит объединенный словарь

У меня есть библиотека CommonLibraryWpfThemes с несколькими файлами XAML в словаре ресурсов. My Themes/Generic.xml содержит объявление ResourceDictionary.MergedDictionaries, которое объединяет все остальные файлы.

Generic.xaml

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary
            Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/BrushDictionary.xaml" />
        <ResourceDictionary
            Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/TextBlockDictionary.xaml" />
        <ResourceDictionary
            Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/LabelDictionary.xaml" />
        <ResourceDictionary
            Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/ButtonDictionary.xaml" />
        <ResourceDictionary
            Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/WindowDictionary.xaml" />
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

В моем проекте приложения у меня есть ссылка на CommonLibraryWpfThemes, и я явно ссылаюсь на Generic.xml в моем файле App.xaml.

App.xaml - FAILS

<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
            Source="/CommonLibraryWpfThemes;component/Themes/Generic.xaml" />
    </Application.Resources>
</Application>

Это не работает. При запуске приложения появляется следующая ошибка:

System.Windows.Markup.XamlParseException occurred
  Message="Cannot find resource named '{_fadedOrangeBrush}'. Resource names are case sensitive.  Error at object 'System.Windows.Setter' in markup file 'CommonLibraryWpfThemes;component/ResourceDictionaries/WindowDictionary.xaml' Line 18 Position 13."
  Source="PresentationFramework"
  LineNumber=18
  LinePosition=13

Если я размещаю содержимое Generic.xaml в App.xaml напрямую, все работает нормально:

App.xaml - SUCCEEDS

<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/ResourceDictionaries/BrushDictionary.xaml" />
                <ResourceDictionary
                    Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/TextBlockDictionary.xaml" />
                <ResourceDictionary
                    Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/LabelDictionary.xaml" />
                <ResourceDictionary
                    Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/ButtonDictionary.xaml" />
                <ResourceDictionary
                    Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/WindowDictionary.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Возможно, я поменяю это неправильно. Моя цель - упростить ссылку на все мои тематические ресурсы из нескольких приложений без необходимости перечислять все отдельные файлы. Есть ли рекомендуемый способ сделать это? (Примечание: я не пытаюсь переключаться между несколькими темами - у меня есть только одна тема.)

В качестве бонуса было бы неплохо, если бы кто-нибудь мог рассказать мне, как ссылаться на ресурсы во внешней библиотеке, не нарушая конструктор в Visual Studio.

Спасибо.

EDIT:

Я попытался обернуть ResourceDictionary в элементе ResourceDictionary.MergedDictionary, но это также не сработало (я получаю ту же ошибку):

<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>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Ответ 1

Ответ на аналогичный вопрос здесь ранее, см. Добавление объединенного словаря в объединенный словарь.

Это ошибка оптимизации, см. Стиль Microsoft Connect/DefaultStyleKey не найден во внутренних MergedDictionaries:

О создании каждого объекта в XAML, если присутствует стиль по умолчанию (т.е. стиль с ключом типа), который стиль должен применяться. Как вы можете представьте, что есть несколько характеристик оптимизация, чтобы сделать это (подразумеваемое) найдите легкий вес, насколько это возможно. Один из них заключается в том, что мы не заглядываем внутрь Словари ресурсов, если они не являются помечено как "содержащий значение по умолчанию Стили". Есть ошибка: если все ваши стили по умолчанию вложены в объединенные словарей на трех уровнях (или глубже), верхний словарь не получите флаг, чтобы поиск пропускал его. Работа вокруг заключается в том, чтобы по умолчанию Стиль к чему-то, что угодно, в корневой словарь.

Таким образом, добавление фиктивного стиля в корневой словарь исправляет это. Пример

<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>   

Ответ 2

Проверьте свой конструктор в App.xaml.cs-вызовах InitializeComponent() - вот что объединяет словари ресурсов...

Ответ 3

Вам не нужно ссылаться на generic.xaml вообще, он имеет встроенную поддержку. Это, однако, означает, что он предоставляет стиль по умолчанию, который вы не устанавливаете явно. Явное задание стилей/шаблонов должно быть доступно из явных ссылок на словари.

(EDIT для ясности)

Единственным исключением является App.xaml, где определенные ресурсы становятся доступными для всего приложения, без необходимости ссылаться на какой-либо конкретный словарь ресурсов. Сам ресурс должен быть доступен по имени.

Причина, по которой это не удается

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

я думаю, потому что вы не обернули его в обертку MergedDictionary, добавив ее в объединенные словари. Добавление непосредственно к ресурсам работает только для ресурсов, которые вы объявляете локально, например. сами стили и т.д.

Однако, как я уже говорил, вам не нужно объединять generic.xaml в любом месте, возможно, вам нужно просто реорганизовать кисти и другие ресурсы, используемые за пределами стилей, и объединить только те ресурсы в App.xaml.

Также обратите внимание, что стили не обязательно должны быть в generic.xaml, чтобы иметь поведение по умолчанию - если для него доступен стиль с ключом, равным типу элемента (глобально или в локальных ресурсах), тогда он будет использовать стиль как стиль по умолчанию. generic.xaml - просто удобство.

Отметьте этот ответ.

Для других пользовательских кистей и т.д. вам необходимо явно ссылаться на эти ресурсы.

Вы также должны проверить содержимое WindowDictionary.xaml, эта ошибка имеет определенный запах.

Ответ 4

Я получал эту ошибку в своих модульных тестах, и ответ Криса сверху дал мне ключ, который мне нужен. В основном на моем первом проверенном методе я поставил:

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

И вдруг он смог найти мой шаблон для моих страниц. Примечание: это означает, что вам нужно проверить, существует ли экземпляр вашего приложения, если вы также тестируете устройство App.cs.

Ответ 5

Мое решение здесь, нажмите "Обходные решения".