Этот проект добавляет поддержку тем в приложениях .NET Winforms. Этот проект поддерживает как нестандартные, так и пользовательские темы и использует наш проект Winforms-Stylable-Controls для стиля управления, которым не хватает поддержки стиля.
Во -первых, установите инструмент ReportGenerator:
dotnet tool install -g dotnet-reportgenerator-globaltool
Далее создайте отладочную версию проекта:
dotnet build WinFormsThemes/WinFormsThemes.sln -c Debug
Отчет о покрытии тестирования может быть создан с помощью:
rmdir /s /q WinFormsThemesTestProjectTestResults
dotnet test WinFormsThemes/TestProject --no-build --verbosity normal --collect:"XPlat Code Coverage"
reportgenerator -reports:WinFormsThemesTestProjectTestResults*coverage.cobertura.xml -targetdir:WinFormsThemesTestProjectTestResultshtml -reporttypes:Html -sourcedirs:WinFormsThemesWinFormsThemes
start "" WinFormsThemesTestProjectTestResultshtmlindex.html
Мы используем stryker.net для тестирования на мутации. Чтобы запустить тесты на мутацию, используйте:
dotnet tool restore
dotnet stryker
ВАЖНО: Не запускайте Stryker в каталоге проекта - вам нужно запустить его в Dir Solution Dir, в противном случае конфигурация не будет найдена!
Чтобы использовать этот проект, вам необходимо добавить ссылку на наш пакет Nuget ( dotnet add package AssortedDevelopment.WinFormsThemes ).
Примечание. В настоящее время этот проект требует .NET 6.0 или выше.
Далее вам нужно настроить темы:
var registry = ThemeRegistryHolder . GetBuilder ( ) . Build ( ) ;
var theme = registry . ThemeRegistry . GetTheme ( ) ; Это, например, может быть размещено в Program.cs вашего приложения и использует настройки по умолчанию для поиска тем, возврата реестра и использовать его стандартную тему.
Наконец, вам необходимо предоставить тему всем формам, чтобы быть тематической и добавить одну строку в событие Load :
theme . Apply ( this ) ;Это применит эту тему на данной форме и всех детях.
Конечно, вы можете расширить эту библиотеку и настроить обработку в соответствии с вашими потребностями. Вот несколько примеров:
Если вы хотите отладить проблему с этой библиотекой, вы можете включить регистрацию в IThemeRegistryBuilder :
ThemeRegistryHolder . GetBuilder ( ) . SetLoggerFactory ( LoggerFactory ) . Build ( ) ; Это зарегистрирует все действия библиотеки в данную ILoggerFactory .
ПРИМЕЧАНИЕ. Любые вызовы перед вызовом SetLoggerFactory не будут затронуты, поэтому мы советуем вызову SetLoggerFactory как можно раньше.
Если в вашем проекте нет инъекции зависимости, мы предоставляем утилиты, чтобы сделать как IThemeRegistry , так и ITheme в мире
IThemeRegistry Для IThemeRegistry , мы предоставляем класс ThemeRegistryHolder , который можно использовать для хранения реестра и получения его позже: ThemeRegistryHolder . ThemeRegistry = ThemeRegistryHolder . GetBuilder ( ) . Build ( ) ; После этого вы можете получить реестр из любой точки приложения, используя: var registry = ThemeRegistryHolder.ThemeRegistry;
ITheme для ITheme , IThemeRegistry предоставляет Current свойство, которое можно использовать для получения текущей темы. Чтобы это работало, вам необходимо настроить селектор, который определяет текущую тему: private ITheme SelectCurrentTheme ( IThemeRegistry registry )
{
//logic to select theme here
}
.. .
ThemeRegistryHolder . ThemeRegistry = ThemeRegistryHolder . GetBuilder ( ) . WithCurrentThemeSelector ( SelectCurrentTheme ) . Build ( ) ; Это позволяет использовать IThemeRegistry.Current для получения текущей темы и IThemeRegistry.OnThemeChanged для уведомления об изменениях:
var mytheme = ThemeRegistryHolder . ThemeRegistry . Current ;
ThemeRegistryHolder . ThemeRegistry . OnThemeChanged += ( sender , args ) =>
{
//logic to handle theme change here
} ; По умолчанию наша библиотека будет соблюдать настройки операционной системы в отношении темного режима и высокого контраста при вызове GetTheme . Если вы хотите добавить дополнительные критерии выбора или вы хотите дать пользователю возможность переопределить этот выбор, вы можете сделать это легко. Вместо того, чтобы полагаться на настройки по умолчанию в IThemeRegistry.GetTheme() вы можете установить IThemeRegistry.Current для любой темы, которую вы хотите, предоставив CurrentThemeSelector :
IThemeRegistry registry = ThemeRegistryHolder . GetBuilder ( )
. WithCurrentThemeSelector ( registry => registry . GetTheme ( ) )
. Build ( ) ;
var selectedTheme = registry . CurrentTheme ;Из коробки есть 2 способа добавить индивидуальные темы:
.theme.json , хранящиеся в каталоге themes , работающего рабочего режима.CONFIG_THEMING_THEME_Оба способа используют один и тот же формат JSON для определения темы (версия определяет формат файла). Простым примером этого может быть:
{
"name" : " theme-name " ,
"capabilities" : [ " DarkMode " , " HighContrast " ],
"version" : 3 ,
"variables" : {
"backColor" : " #082a56 " ,
"foreColor" : " #082a57 "
},
"colors" : {
"backColor" : " backColor " ,
"foreColor" : " foreColor " ,
"controls" : {
"backColor" : " backColor " ,
"foreColor" : " foreColor "
}
}
}Для получения полного списка доступных настроек, пожалуйста, проверьте нашу схему JSON здесь.
Если эти 2 способа не являются достаточно гибкими, вы можете реализовать тему самостоятельно и зарегистрировать ее, используя пользовательский источник темы (см. Ниже): предпочтительным способом является AbstractTheme подкласс, так как вам просто нужно реализовать базовые цвета и, необязательно, переопределить расширенные цвета - стиль управления выполняется базовым классом.
Более продвинутый способ - это реализация интерфейса ITheme . Это только поддерживает основную инфраструктуру, такую как возможности темы, но стиль полностью в ваших руках.
Просмотры могут быть добавлены либо путем реализации IThemeLookup (см. Ниже), либо добавив его непосредственно к строителю:
ThemeRegistryHolder . GetBuilder ( )
. WithThemes ( )
. AddDefaultThemes ( )
. AddTheme ( new MySuperDarkTheme ( ) )
. FinishThemeList ( )
. Build ( ) ; Если вы хотите добавить другой источник темы, помимо файлов и ресурсов (например, при реализации пользовательских реализаций ITheme или AbstractTheme ) или просто хотите изменить путь папки, вы можете добавить пользовательскую реализацию IThemeLookup , которая обрабатывает поиск доступных тем:
internal class MyThemeLookup : IThemeLookup
{
public int Order => 999 ; //highest order wins when 2 lookups return the same theme name
public List < ITheme > Lookup ( )
{
List < ITheme > results = new List < ITheme > ( ) ;
//implement search for themes here
return results ;
}
}
}После этого вам нужно зарегистрировать этот класс в строительном застройке:
ThemeRegistryHolder . GetBuilder ( )
. WithThemes ( )
. AddDefaultThemes ( )
. WithLookup ( )
. FinishThemeList ( )
. Build ( ) ;Поскольку мы не хотим заставлять вас использовать конкретную библиотеку управления Winforms, в настоящее время мы поддерживаем только стиль стандартных элементов управления и элементов управления в нашем проекте Winforms-Stylable-Controls. Как мы понимаем, вы, возможно, также захотите создать другие элементы управления, мы поддерживаем добавление специализированных плагинов для обработки стиля определенного типа управления. Для этого вам нужно реализовать ``:
internal class MyCustomControlThemePlugin : AbstractThemePlugin < MyCustomControl >
{
protected override void ApplyPlugin ( MyCustomControl mcc , AbstractTheme theme )
{
//style control based on the colors available in the Theme
}
}Наконец, вам просто нужно зарегистрировать его для правильного типа:
ThemeRegistryHolder . GetBuilder ( )
. AddThemePlugin ( new MyCustomControlThemePlugin ( ) )
. Build ( ) ;Примечание. В настоящее время мы поддерживаем только непосредственно зарегистрированные типы. Подклассы не будут стилизованы автоматически!
Пожалуйста, просмотрите руководство для получения дополнительной информации.