Я хотел бы услышать несколько советов относительно ресурсов и UserControls
...
Я понял, что UserControls
иногда имеет свойства, которые я хочу настроить - но в глобальном масштабе и не для экземпляра .
Позвольте мне привести пример:
Я реализовал UserControl
, который в основном представляет собой вкладку (я называю этоRibbonTab
):
Пример RibbonTab
Каждая вкладка имеет свой собственный значок и текст (и некоторые другие свойства), которые все DependencyProperties
, так что я могу создать экземплярмои вкладки вот так:
<!-- Time Tracking Tab -->
<UserControls:RibbonTab
Icon="{StaticResource TimeTrackingTabIcon}"
Text="{StaticResource TimeTrackingTabHeaderString}"
LabelMode="AutoResize" ResizePriority="0"
Command="{Binding LoadTimeTrackingViewModelCommand}"/>
<!-- Vacation Tab -->
<UserControls:RibbonTab
Icon="{StaticResource VacationTabIcon}"
Text="{StaticResource VacationTabHeaderString}"
LabelMode="AutoResize" ResizePriority="1"
Command="{Binding LoadVacationViewModelCommand}"/>
<!-- Payout Tab -->
<UserControls:RibbonTab
Icon="{StaticResource PayoutTabIcon}"
Text="{StaticResource PayoutTabHeaderString}"
LabelMode="AutoResize" ResizePriority="2"
Command="{Binding LoadPayoutViewModelCommand}"/>
Как видите, цвет фона выбранной вкладки белый.В настоящее время это фиксированное значение в пределах ControlTemplate
.Мне бы хотелось, чтобы это настраивалось вместо этого.
Я разобрался с различными возможными решениями, но я не уверен, если я продумал:
1.) Используйте свойство DependencyProperty
Я мог бы представить еще один DependencyProperty
, например "SelectedTabColor"
, и создать вкладки следующим образом:
<!-- Time Tracking Tab -->
<UserControls:RibbonTab
<!-- All of the previous properties go here... -->
SelectedTabColor="White"/>
<!-- Vacation Tab -->
<UserControls:RibbonTab
<!-- All of the previous properties go here... -->
SelectedTabColor="White"/>
<!-- Payout Tab -->
<UserControls:RibbonTab
<!-- All of the previous properties go here... -->
SelectedTabColor="White"/>
Легко видеть, что этот метод требует многократного присоединения значений, новы действительно просто хотите установить это свойство один раз (глобально) и все будет готово.
2.) Используйте ResourceDictionary
Я мог бы сделать UserControl
ссылку на StaticResource
из приложения ResourceDictionary
:
<UserControl x:Class="MyApp.View.UserControls.RibbonTab">
<Grid>
<!-- Lots of stuff omitted here... -->
<Rectangle Fill="{StaticResource RibbonTab_SelectedTabColor}"/>
<!-- More stuff omitted here... -->
</Grid>
</UserControl>
Но тогда мой UserControl
требует, чтобы приложение / интеграция имели StaticResource
, который назван именно так.Перенос UserControl
в другой проект был бы кошмаром ...
3.) Использование UserControl.Resources + StaticResources
Другая возможность заключается в использовании Resources
атрибут UserControl
и поместите его обязательные определения как StaticResources
непосредственно там:
<UserControl x:Class="MyApp.View.UserControls.RibbonTab">
<UserControl.Resources>
<!--#region Configurable properties -->
<Color x:Key="SelectedTabColor">White</Color>
<!--#endregion Configurable properties -->
</UserControl.Resources>
<Grid>
<!-- Lots of stuff omitted here... -->
<Rectangle Fill="{StaticResource SelectedTabColor}"/>
<!-- More stuff omitted here... -->
</Grid>
</UserControl>
Это имеет приятный штрих, поскольку каждый StaticResource
хранится вместе с элементом, который фактически использует его, вместоиметь большой ResourceDictionary
и потерять отслеживание того, что используется где.
Однако недостатком является то, что вы не можете повторно использовать общее определение (скажем, приложение определяет определенный цвет акцента в его ResourceDictionary
) для нескольких UserControls
, но приходится переопределять его везде, чтозатрудняет обслуживание.
4.) Используйте UserControl.Resources + ResourceKeys
Лучший подход, который я мог придумать, - определить StaticResources
с помощьюResourceKeys
(вместо фактических значений) в Resources
UserControl
.Интегратор должен установить ResourceKeys
для существующих ресурсов приложения:
<UserControl x:Class="MyApp.View.UserControls.RibbonTab">
<UserControl.Resources>
<!--#region Configurable properties -->
<!-- Integration hint: Set ResourceKey to your own definition! -->
<StaticResource x:Key="SelectedTabColor"
ResourceKey="AppHighlightedElementAccentColor"/>
<!--#endregion Configurable properties -->
</UserControl.Resources>
<Grid>
<!-- Lots of stuff omitted here... -->
<Rectangle Fill="{StaticResource SelectedTabColor}"/>
<!-- More stuff omitted here... -->
</Grid>
</UserControl>
Я еще не оценил это подробно.Единственный недостаток, который я вижу сейчас, заключается в том, что тип ссылочного ресурса проверяется только во время выполнения, но не во время разработки.
Я упускаю очевидное ...?Есть ли элегантный способ решить эту проблему?Было бы здорово услышать некоторые мнения, потому что сейчас я немного не уверен в том, как поступить ...