Проблема со ссылкой на словарь ресурсов, который содержит объединенный словарь
У меня есть библиотека 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
Мое решение здесь, нажмите "Обходные решения".