Как ссылаться на клавиши стиля WPF, определенные в отдельной сборке в другой библиотеке
У меня есть две библиотеки и один макет проекта сборки приложений, и мне интересно, как я могу ссылаться на стили по их ключу в одной из моих библиотек, которые определены в другой.
Схема моего решения:
- WpfControls.dll - содержит общие элементы многократного использования, такие как элемент управления NumericUpDown на основе WPF, а также другие базовые элементы управления и некоторые стили, которые я хотел бы сделать повторно используемыми. Ради примера можно сказать, что мой ключ стиля здесь определяется как MyButtonStyle.
- SpecializedControls.dll. Удерживает элементы управления, которые специализированы для нашего приложения, такие как настраиваемые составные элементы управления и UserControls в WPF. Здесь я хотел бы ссылаться на стиль MyButtonStyle, определенный в сборке WpfControls.dll.
- Application.exe. Эта сборка использует элементы управления, определенные в сборке SpecializedControls.dll.
Я видел несколько примеров, объясняющих, как это сделать с помощью простой единой библиотеки управления и сборки приложения, но в моем случае у меня есть две сборки и приложение. Таким образом, другими словами, в моем случае у меня нет App.xaml в моей второй библиотеке управления, где я мог бы использовать концепцию MergeDictionaries. Я уверен, что если бы мне захотелось добавить ссылку MergedDictionaries непосредственно в каждый элемент управления XAML, чтобы объединить все Generic.xaml, определенные в сборке WpfControls.dll, но я предполагаю, что это приведет к тому, что стили будут излишне слиты в разные места в моей сборке SpecializedControls, которая не кажется лучшим решением. Что еще хуже, эти словари также могут быть объединены в Application.exe, это начинает раздувать мое приложение во время выполнения?
Может кто-нибудь уточнить, какой рекомендуемый или лучший подход для обмена такими стилями с наименьшим количеством программных и ресурсных издержек.
Обновление. После немного более сложного тестирования кажется, что у меня возникли проблемы с ссылкой на любой ресурс, определенный в Generic.xaml, его ключом даже внутри той же сборки. Возможно, что-то совершенно не так, как я понимаю, как работают ключи ресурсов, поэтому мне придется немного больше исследований, а также изучить ComponentResourceKey. Если у кого-нибудь есть какие-либо намеки или предложения, пожалуйста, помогите.
Ответы
Ответ 1
Поиск ресурсов в WPF работает в иерархии: вверх по логическому дереву, затем ресурсам приложений, тематическим ресурсам и, наконец, системным ресурсам.
Ресурсы темы обычно могут быть доступны только неявно (даже в пределах сборки, которую они определены). Это относится только к стилям, где TargetType может использоваться как неявный ключ.
Чтобы выполнить то, что вы пытаетесь сделать, есть два варианта:
-
Используйте ComponentResourceKey. Это специальный ключ ресурса, который позволяет ссылаться на ресурсы из других сборок. Например, вы можете определить кисть в словаре темы WpfControls:
<LinearGradientBrush x:Key="{ComponentResourceKey TypeInTargetAssembly=local:MyClass, ResourceId=MyBrush}">
<GradientStop Color="Red" />
<GradientStop Color="Blue" Offset="1" />
</LinearGradientBrush>
И затем вы можете ссылаться на него в SpecializedControls:
<UserControl Background="{StaticResource {ComponentResourceKey TypeInTargetAssembly=wpfControls:MyClass, ResourceId=MyBrush}}" />
-
Используйте MergedDictionaries, чтобы импортировать словарь в ресурсы приложения. Вы можете сделать это в сборке приложений, и когда приложение загрузится, даже те элементы управления, которые находятся в SpecializedControls, смогут использовать эти ресурсы. У вас возникнет проблема с опытом разработки в этом сценарии, который вы можете решить, поставив поддельный App.xaml в SpecializedControls, который также будет содержать ссылку на словарь.
Надеюсь, что это поможет,
Aelij.
Ответ 2
Принятый ответ правильный, я просто объясняю, как использовать MergedDictionaries
В App.xaml,
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/-YourDllName-;component/-DirectoryName-/FileName.xaml"/>
<!-- Use Below syntax if your resource file is not inside a directory(in root) -->
<ResourceDictionary Source="pack://application:,,,/-YourDllName-;component/FileName.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>