Загрузка/использование ресурсных словарей из встроенного WPF-элемента WinForms
У меня есть приложение Windows Forms, которое должно содержать элемент управления WPF во время выполнения. У меня есть базовый хостинг и взаимодействие (с помощью элемента управления ElementHost), и все работает нормально, пока я не попытаюсь сделать что-то, что требует, чтобы элемент управления WPF использовал определенные пользовательские словари ресурсов, которые определены. (Элемент управления WPF и все его ресурсные словари определены в одной и той же DLL библиотеки управления WPF.)
Как только это произойдет, я получаю кучу ошибок, которые выглядят так:
System.Windows.ResourceDictionary Warning: 9 : Resource not found; ResourceKey='DocumentHeaderInterestStyle'
Я нашел ссылку ссылка ( ссылка кажется мертвой из-за архивирования, this может быть той же статьей, на которую первоначально ссылались). что об этом говорит, но похоже, что статья приближается к чему-то еще со стороны WPF, но я действительно не хочу вносить изменения в элемент управления WPF, поскольку все работает в автономном приложении WPF.
Если единственный способ сделать это - внести изменения со стороны WPF, я могу получить эти изменения (я не несу ответственность за библиотеку управления WPF, но человек, который также работает для той же компании, проблема, отличная от времени, чтобы внести изменения.), но я надеюсь на то, что я могу сделать на стороне WinForms, чтобы заставить это работать.
В библиотеке управления WPF есть файл словаря ресурсов с именем "Default.xaml", определенный в проекте со следующими свойствами:
Действие сборки: Страница
Копировать в выходной каталог: не копировать
Пользовательский инструмент: MSBuild: компиляция
В автономном приложении WPF есть следующая запись в файле App.xaml:
<ResourceDictionary x:Uid="ResourceDictionary_1">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary x:Uid="ResourceDictionary_2" Source="/SmartClient.Infrastructure;component/Themes\Default.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Кажется, что библиотека управления уже должна знать, как получить свои ресурсы. Использование Resource.MergedDictionaries.Add() кажется, что оно должно работать, но где я могу получить экземпляр существующего словаря?
Ответы
Ответ 1
Предполагая, что вы знаете, какие ресурсы вам нужны (звучит так, как вы), вы должны просто "сами" их вводить. Что-то вроде:
var wpfControl = new ...;
wpfControl.Resources.Add(...);
elementHost.Child = wpfControl;
В вашем вопросе вы упомянули, что в библиотеке управления есть существующие ресурсные словари. Если это так, вы можете просто сделать это:
var wpfControl = new ...;
wpfControl.Resources.MergedDictionaries.Add(/* instance of existing dictionary */);
elementHost.Child = wpfControl;
Ответ 2
Для загрузки ресурсных словарей, встроенных в сборку, я использовал следующий фрагмент для загрузки их во время выполнения:
//using System.Windows
ResourceDictionary dict = new ResourceDictionary();
dict.Source = new Uri("MyResourceDictionary.xaml", UriKind.Relative);
Application.Current.Resources.MergedDictionaries.Add(dict);
Это также будет работать для загрузки словаря в исполняемый каталог.
Ответ 3
Предположим, что ваши стили/шаблоны/ресурсы разделены на множество файлов Resources1.xaml
и Resources2.xaml
, вы можете объединить их в один ресурсный словарь (AllResources.xaml
). Словарь ресурсов можно легко добавить в элемент управления в файле управления xaml. См. Пример ниже.
(!) Задайте Resources1.xaml
, Resources2.xaml
и AllResources.xaml
действия сборки Page
Resources1.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ControlTemplate x:Key="ScrollViewerControlTemplate" TargetType="{x:Type ScrollViewer}">
...
</ControlTemplate>
<LinearGradientBrush x:Key="VerticalScrollBarBackground" EndPoint="1,0" StartPoint="0,0">
...
</LinearGradientBrush>
<Style x:Key="StyleA" TargetType="{x:Type ScrollBar}">
...
</Style>
</ResourceDictionary>
Resources2.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="StyleB" TargetType="{x:Type ScrollBar}">
...
</Style>
<Style x:Key="StyleC" TargetType="{x:Type TextBlock}">
...
</Style>
</ResourceDictionary>
AllResources.xaml
Добавьте источники ресурса ресурса как относительные пути в AllResources.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources1.xaml" />
<ResourceDictionary Source="Resources2.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Наконец, в вашем UserControl
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/projectName;component/PathToTheFileRelativeToProjectRootDirectory/AllResources.xaml
<converters:StringToUpperCaseConverter x:Key="StringToUpperCaseConverter" />
<converters:LocalizationEntryToStringCaseConverter x:Key="LocalizationEntryToStringCaseConverter" />
</ResourceDictionary>
</UserControl.Resources>