Использование преимуществ тем Windows было бы одним из способов решения этой проблемы.Большая часть этого перефразирована и усечена из Windows Presentation Foundation, развернутого Адамом Натаном.
Простой подход
Вы можете использовать открытые ресурсы и ключина SystemColors
, SystemFonts
и SystemParameters
в вашем шаблоне управления (вместе с DynamicResource
, если тема изменяется во время работы вашей программы), чтобы установить соответствующие значения:
Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
Надежный подход
Лучший способ, хотя он требует больше работы, - это иметь шаблон элемента управления для каждой темы, а не один набор, который переопределяет все.Для этого вы должны поместить все ресурсы, относящиеся к вашей теме, в собственный словарь ресурсов.Эти словари находятся в подпапке themes в корне вашего проекта, и каждый из них назван в честь названия темы и цвета темы: ThemeName.ThemeColor.xaml.
Обратите внимание, что вы все еще используетеSystemColors
, SystemFonts
и SystemParameters
, как в простом подходе.
У меня нет более новой редакции книги, в которой, вероятно, перечислены темы Windows 7, но вот список Адамав издании у меня есть:
- Vista Aero: themes \ Aero.NormalColor.xaml
- XP по умолчанию: themes \ Luna.NormalColor.xaml
- XP зеленый:themes \ Luna.Homestead.xaml
- XP silver: themes \ Luna.Metallic.xaml
- XP royale: themes \ Royale.NormalColor.xaml
- XP Zune: темы \Zune.NormalColor.xaml
- Classic: themes \ Classic.xaml
Они будут автоматически загружены и отключены при смене темы.Вы также можете указать themes \ Generic.xaml по умолчанию, когда он пытается загрузить тему, которой не соответствует созданный словарь ресурсов.
Вы также должны включить автоматическое создание тем с помощьюThemeInfoAttribute
:
//look inside this assembly
[assembly:ThemeInfo(ResourceDictionaryLocation.SourceAssembly,
ResourceDictionaryLocation.SourceAssembly)]
ResourceDictionaryLocation
также имеет опцию ExternalAssembly
.Соглашение об именах для этих внешних сборок - MainAssembly.ThemeName.dll, поэтому, если ваша сборка называется MyApp, она будет искать словарь ресурсов классической темы в MyApp.Classic.dll.
И, наконец, вы используете ThemeDictionaryExtension
в словаре ресурсов вашего приложения:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="{ThemeDictionary MyApp}"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Если вы создаете какие-либо пользовательские элементы управления, производные от другого элемента управления (например, не UserControl
, а ProgressBar
), вы должны сделать это в его статическомконструктор:
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl),
new FrameworkPropertyMetadata(typeof(MyControl)));