WPF 实现更换主题色

 WPF 实现更换主题色

WPF 使用 WPFDevelopers.Minimal 如何更换主题色

作者:WPFDevelopersOrg

原文链接:    https://github.com/WPFDevelopersOrg/WPFDevelopers.Minimal

  • 框架使用大于等于.NET40

  • Visual Studio 2022;

  • 项目使用 MIT 开源许可协议;

  • Nuget Install-Package WPFDevelopers.Minimal 3.2.6-preview

  • 定义一个公共颜色资源文件,所有控件都动态资源引用DynamicResource颜色的Key,然后这样修改一个资源文件的Key  SolidColorBrushColor颜色值就可以实现更换主题色;

  • 此篇主要是定义了多个公共颜色资源文件如下,选择不同的资源文件进行更换App.xaml的资源字典实现更换主题色;

    • Application.Current.Resources.MergedDictionaries.Remove(Blue) 字典寻找Blue,然后移除Application.Current.Resources.MergedDictionaries.Add(Green); 就完成更换主题色;

    • 创建 Light.Blue

    • 创建 Light.Green

    • 创建 Light.Orange

    • 创建 Light.Pink

    • 创建 Light.Purple

    • 创建 Light.Purple7bd5469f7ef23542f8a877422422679a.png

  • 使用 WPFDevelopers.Minimal 如何更换主题色Nuget包大于等于3.2.3如下;

  • 新增主题色如下;

    • 新建资源文件Light.Carmine.xaml如下,自己更换颜色值即可;

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:po="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" po:Freeze="True"><!--Default颜色--><Color x:Key="DefaultBorderBrushColor" po:Freeze="True">#CD7474</Color><SolidColorBrush x:Key="DefaultBorderBrushSolidColorBrush" Color="{StaticResource DefaultBorderBrushColor}" po:Freeze="True"></SolidColorBrush><Color x:Key="DefaultBackgroundColor" po:Freeze="True">#CFA0A0</Color><SolidColorBrush x:Key="DefaultBackgroundSolidColorBrush" Color="{StaticResource DefaultBackgroundColor}" po:Freeze="True"></SolidColorBrush><Color x:Key="DefaultBackgroundPressedColor" po:Freeze="True">#B70404</Color><SolidColorBrush x:Key="DefaultBackgroundPressedSolidColorBrush" Color="{StaticResource DefaultBackgroundPressedColor}" po:Freeze="True"></SolidColorBrush><!--Primary颜色--><Color x:Key="PrimaryNormalColor" po:Freeze="True">#B31B1B</Color><SolidColorBrush x:Key="PrimaryNormalSolidColorBrush" Color="{StaticResource PrimaryNormalColor}" po:Freeze="True"></SolidColorBrush><SolidColorBrush x:Key="WindowBorderBrushSolidColorBrush" Color="{StaticResource PrimaryNormalColor}" po:Freeze="True"></SolidColorBrush><Color x:Key="PrimaryMouseOverColor" po:Freeze="True">#BB5F5F</Color><SolidColorBrush x:Key="PrimaryMouseOverSolidColorBrush" Color="{StaticResource PrimaryMouseOverColor}" po:Freeze="True"></SolidColorBrush><Color x:Key="PrimaryPressedColor" po:Freeze="True">#B70404</Color><SolidColorBrush x:Key="PrimaryPressedSolidColorBrush" Color="{StaticResource PrimaryPressedColor}" po:Freeze="True"></SolidColorBrush></ResourceDictionary>
  • 1)把上面新增的资源添加App.xaml中即可;

<Application x:Class="WPFDevelopers.Minimal.Sample.App"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:ws="https://github.com/WPFDevelopersOrg.WPFDevelopers.Minimal"StartupUri="ExampleViews\MainView.xaml" ShutdownMode="OnMainWindowClose"><Application.Resources><ResourceDictionary><ResourceDictionary.MergedDictionaries><ResourceDictionary Source="pack://application:,,,/WPFDevelopers.Minimal.Sample.Net40;component/Light.Carmine.xaml"/><!--需要注意ws:Resources 必须再配色主题后,Theme="Dark" 为黑色皮肤 --><ws:Resources Theme="Light"/><ResourceDictionary Source="pack://application:,,,/WPFDevelopers.Minimal;component/Themes/Theme.xaml"/></ResourceDictionary.MergedDictionaries></ResourceDictionary></Application.Resources>
</Application>
  • 2)或者把资源添加到ThemesCollection集合中;

if (ThemesCollection != null)ThemesCollection.Add(new ThemeModel{Color = "#B31B1B",ResourcePath ="pack://application:,,,/WPFDevelopers.Minimal.Sample.Net40;component/Light.Carmine.xaml"});
  • 重启应用效果如下;

1f717d599146a557f9586dcdd5aab94d.pngbf5310209d44c6fe91bba761385476ff.png

1)ThemeControl.cs代码如下;

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using WPFDevelopers.Minimal.Helpers;
using WPFDevelopers.Minimal.Models;namespace WPFDevelopers.Minimal.Controls
{public class ThemeControl : Control{public static readonly DependencyProperty ItemsSourceProperty =DependencyProperty.Register("ItemsSource", typeof(ObservableCollection<ThemeModel>), typeof(ThemeControl),new PropertyMetadata(null));static ThemeControl(){DefaultStyleKeyProperty.OverrideMetadata(typeof(ThemeControl),new FrameworkPropertyMetadata(typeof(ThemeControl)));}public ObservableCollection<ThemeModel> ItemsSource{get => (ObservableCollection<ThemeModel>)GetValue(ItemsSourceProperty);set => SetValue(ItemsSourceProperty, value);}public override void OnApplyTemplate(){base.OnApplyTemplate();ItemsSource = new ObservableCollection<ThemeModel>();ItemsSource.Add(new ThemeModel{Color = "#409EFF",ResourcePath = "pack://application:,,,/WPFDevelopers.Minimal;component/Themes/Light.Blue.xaml"});ItemsSource.Add(new ThemeModel{Color = "#FF033E",ResourcePath = "pack://application:,,,/WPFDevelopers.Minimal;component/Themes/Light.Red.xaml"});ItemsSource.Add(new ThemeModel{Color = "#A21BFC",ResourcePath = "pack://application:,,,/WPFDevelopers.Minimal;component/Themes/Light.Purple.xaml"});ItemsSource.Add(new ThemeModel{Color = "#FE9426",ResourcePath = "pack://application:,,,/WPFDevelopers.Minimal;component/Themes/Light.Orange.xaml"});ItemsSource.Add(new ThemeModel{Color = "#00B050",ResourcePath = "pack://application:,,,/WPFDevelopers.Minimal;component/Themes/Light.Green.xaml"});ItemsSource.Add(new ThemeModel{Color = "#FF007F",ResourcePath = "pack://application:,,,/WPFDevelopers.Minimal;component/Themes/Light.Pink.xaml"});if (ThemeCache.ThemesDictCache.Count > 0)foreach (var item in ThemeCache.ThemesDictCache)if (ItemsSource.Any(x => x.Color != item.Key))ItemsSource.Add(item.Value);SelectChecked();ItemsSource.CollectionChanged += ItemsSource_CollectionChanged;foreach (var theme in ItemsSource)theme.PropertyChanged += Theme_PropertyChanged;}private void SelectChecked(){var existsTheme = ItemsSource.FirstOrDefault(y =>Application.Current.Resources.MergedDictionaries.ToList().Exists(j =>j.Source != null && y.ResourcePath.Contains(j.Source.AbsoluteUri)));if (existsTheme != null)existsTheme.IsChecked = true;}private void ItemsSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e){switch (e.Action){case NotifyCollectionChangedAction.Add:foreach (ThemeModel item in e.NewItems){if (!ThemeCache.ThemesDictCache.ContainsKey(item.Color))ThemeCache.ThemesDictCache.Add(item.Color, item);item.PropertyChanged += Theme_PropertyChanged;SelectChecked();if (!item.IsChecked) return;ReviseTheme(item);}break;case NotifyCollectionChangedAction.Remove:foreach (ThemeModel item in e.NewItems)if (ThemeCache.ThemesDictCache.ContainsKey(item.Color))ThemeCache.ThemesDictCache.Remove(item.Color);break;case NotifyCollectionChangedAction.Replace:break;case NotifyCollectionChangedAction.Move:break;case NotifyCollectionChangedAction.Reset:break;}}private void Theme_PropertyChanged(object sender, PropertyChangedEventArgs e){if (e.PropertyName == nameof(ThemeModel.IsChecked)){var theme = sender as ThemeModel;if (!theme.IsChecked) return;ReviseTheme(theme);}}private void ReviseTheme(ThemeModel theme){if (theme == null) return;var old = ItemsSource.FirstOrDefault(x => x.IsChecked && x.Color != theme.Color);if (old != null){ItemsSource.Where(y => !y.Color.Equals(theme.Color) && y.IsChecked).ToList().ForEach(h => h.IsChecked = false);var existingResourceDictionary =Application.Current.Resources.MergedDictionaries.FirstOrDefault(x =>x.Source != null && x.Source.Equals(old.ResourcePath));if (existingResourceDictionary != null)Application.Current.Resources.MergedDictionaries.Remove(existingResourceDictionary);var newResource =Application.Current.Resources.MergedDictionaries.FirstOrDefault(x =>x.Source != null && x.Source.Equals(theme.ResourcePath));if (newResource != null) return;var newResourceDictionary = new ResourceDictionary { Source = new Uri(theme.ResourcePath) };Application.Current.Resources.MergedDictionaries.Insert(0, newResourceDictionary);ControlHelper.ThemeRefresh();}}}public class ThemeCache{public static Dictionary<string, ThemeModel> ThemesDictCache = new Dictionary<string, ThemeModel>();}
}

2)Styles.ThemeControl.xaml代码如下;

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:sys="clr-namespace:System;assembly=mscorlib"xmlns:wpfsc="clr-namespace:WPFDevelopers.Minimal.Controls"xmlns:model="clr-namespace:WPFDevelopers.Minimal.Models"><ResourceDictionary.MergedDictionaries><ResourceDictionary Source="../Themes/Basic/ControlBasic.xaml"/><ResourceDictionary Source="../Themes/Basic/Animations.xaml"/></ResourceDictionary.MergedDictionaries><Style TargetType="{x:Type wpfsc:ThemeControl}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type wpfsc:ThemeControl}"><ItemsControl ItemsSource="{Binding ItemsSource,RelativeSource={RelativeSource AncestorType=wpfsc:ThemeControl}}"><ItemsControl.ItemTemplate><DataTemplate><RadioButton Height="40" Width="40" Margin="4,0"Cursor="Hand" IsChecked="{Binding IsChecked}"><RadioButton.Style><Style TargetType="{x:Type RadioButton}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type RadioButton}"><Border x:Name="PART_Border"Padding="2" BorderThickness="0"BorderBrush="{Binding Color}"><Grid Background="{x:Null}"><Rectangle x:Name="PART_Rectangle" Fill="{Binding Color}"/><Path Data="{StaticResource PathCheckMark}"Stretch="Fill" Fill="{DynamicResource BackgroundSolidColorBrush}"VerticalAlignment="Bottom"HorizontalAlignment="Right"Height="10" Width="12"Margin="0,0,4,4"Visibility="{Binding IsChecked,Converter={StaticResource bool2VisibilityConverter}}"/></Grid></Border><ControlTemplate.Triggers><Trigger Property="IsMouseOver" Value="True"><Setter Property="Opacity" Value=".8" TargetName="PART_Rectangle"/><Setter Property="BorderThickness" Value="1" TargetName="PART_Border"/></Trigger><Trigger Property="IsChecked" Value="True"><Setter Property="BorderThickness" Value="1" TargetName="PART_Border"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style></RadioButton.Style></RadioButton></DataTemplate></ItemsControl.ItemTemplate><ItemsControl.ItemsPanel><ItemsPanelTemplate><WrapPanel/></ItemsPanelTemplate></ItemsControl.ItemsPanel></ItemsControl></ControlTemplate></Setter.Value></Setter></Style>
</ResourceDictionary>

3)ThemeControlExample.xaml代码如下;

<!--命名空间-->xmlns:ws="https://github.com/WPFDevelopersOrg.WPFDevelopers.Minimal"<TextBlock Text="Theme" FontSize="20" Margin="0,20,0,0"/><ws:ThemeControl Margin="0,10" ItemsSource="{Binding ThemesCollection,RelativeSource={RelativeSource AncestorType=local:MainView},Mode=OneWayToSource}"/>

ThemeControl|Github[1]
ThemeControl|码云[2]
Styles.ThemeControl.xaml|Github[3]
Styles.ThemeControl.xaml|码云[4]

参考资料

[1]

ThemeControl|Github: https://github.com/WPFDevelopersOrg/WPFDevelopers.Minimal/blob/main/src/WPFDevelopers.Minimal/WPFDevelopers.Minimal.Shared/Controls/ThemeControl.cs

[2]

ThemeControl|码云: https://gitee.com/WPFDevelopersOrg/WPFDevelopers.Minimal/blob/main/src/WPFDevelopers.Minimal/WPFDevelopers.Minimal.Shared/Controls/ThemeControl.cs

[3]

Styles.ThemeControl.xaml|Github: https://github.com/WPFDevelopersOrg/WPFDevelopers.Minimal/blob/main/src/WPFDevelopers.Minimal/WPFDevelopers.Minimal.Shared/Styles/Styles.ThemeControl.xaml

[4]

Styles.ThemeControl.xaml|码云: https://gitee.com/WPFDevelopersOrg/WPFDevelopers.Minimal/blob/main/src/WPFDevelopers.Minimal/WPFDevelopers.Minimal.Shared/Styles/Styles.ThemeControl.xaml

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/283896.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3与vue2的区别

先来说说当下市场开发使用的问题&#xff0c;目前2021年使用vue3开发的企业还是少&#xff0c;基本上都还是以vue2的形式进行开发&#xff0c;vue3的开发模式跟react很像&#xff0c;这时候有人就会想那我学vue3有用么&#xff0c;淦&#xff0c;他喵的&#xff0c;先别激动&am…

Spring Data REST API集成Springfox、Swagger

原文: Documenting a Spring Data REST API with Springfox and Swagger 使用Spring Date REST&#xff0c;你可以迅速为Spring Date repositories的创建REST API&#xff0c;并提供CRUD和更多功能。然而&#xff0c;在严谨的API开发过成功&#xff0c;您还希望拥有自动生成的最…

【系统设计】S3 对象存储

在本文中&#xff0c;我们设计了一个类似于 Amazon Simple Storage Service (S3) 的对象存储服务。S3 是 Amazon Web Services (AWS) 提供的一项服务&#xff0c; 它通过基于 RESTful API 的接口提供对象存储。根据亚马逊的报告&#xff0c;到 2021 年&#xff0c;有超过 100 万…

转: telnet命令学习

1.每天一个linux命令&#xff08;58&#xff09;&#xff1a;telnet命令 转自&#xff1a; http://www.cnblogs.com/peida/archive/2013/03/13/2956992.html telnet命令通常用来远程登录。telnet程序是基于TELNET协议的远程登录客户端程序。Telnet协议是TCP/IP协议族中的一员&a…

禅道、码云、coding、redmine、jira、teambition几大敏捷开发项目管理系统试用对比体验

作为一个软件公司的管理人员&#xff0c;在项目和人员多起来后&#xff0c;就需要通过系统来对项目和人员进行管理。 我们是典型的软件外包公司&#xff0c;专为客户定制软件&#xff0c;所以我们的业务都是项目型的。因此&#xff0c;在管理模式上&#xff0c;我们就要用所谓…

Dubbo中的SPI机制

Dubbo中的SPI机制 概述 Service Provider Interface 即 SPI&#xff0c;是JDK内置的一种服务提供发现机制&#xff0c;可以用来启用框架扩展和替换组件。可以让不同的厂商针对统一接口编写不同的实现 SPI实际上是“接口策略模式配置文件”实现的动态加载机制。在系统设计中&…

JWT:拥有我,即拥有权力

Hi&#xff0c;这里是桑小榆。上篇文章中&#xff0c;我们一起探讨了 OAuth 协议的原理以及授权认证流程&#xff0c;本次我们一起探讨 jwt 令牌作为授权协议的传输介质。OAuth协议规范了几个参与角色的授权标准&#xff0c;安全可控的授予第三方应用&#xff0c;第三方应用获取…

双十一到来之前,阿里AI设计师“鲁班”1天能做4000万张海报

相比较去年&#xff0c;“鲁班”的设计技艺有所提升。 人工智能很大程度上便利了我们的生活&#xff0c;现在他们甚至还能取代了一些设计师的工作&#xff0c;在双十一正式到来之前&#xff0c;淘宝的宣传已经铺天盖地&#xff0c;然而很多人都没想到&#xff0c;我们打开淘宝…

Appium移动自动化测试之获取appPackage和appActivity

方法一&#xff1a;直接打开Appium,点击左上角机器人图标 选择apk所在位置&#xff0c;如图所示&#xff0c;这里以ContactManager.apk为例 方法二&#xff1a;利用dex2jar和jd-gui这两个工具反编译apk文件 这里仍以ContactManager.apk为例 (1)重命名ContactManager.apk为Conta…

CAD转WPF: 关于CAD图纸文件转换为WPF矢量代码文件(xaml文件)的技巧

前言&#xff1a;下面的文章&#xff0c;我将会以几个很简单的步骤&#xff0c;来演示一下通过CAD图纸转换为XAML代码文件的方法&#xff0c;供大佬们参考。一、为了演示一个简单的操作&#xff0c;我此处先打开一个空白的CAD&#xff0c;等下用来进行绘制点内容使用。二、自定…

python之新式类与经典类

经典类与新式类经典类:P 或 P()--深度查找&#xff0c;向上查父节点新式类 :P(object)---广度查找&#xff0c;继承object&#xff0c;新式类的方法较多转载于:https://www.cnblogs.com/zyy98877/p/8574983.html

Flowportal-BPM——环境配置

环境配置&#xff1a; 一、控制面板→程序和功能→打开或不关闭Window功能→选择选项 二、控制面板→管理工具→Internet信息服务&#xff08;IIS&#xff09;管理器→左侧第一个→ISAPI和CGI限制→全部选为【允许】 三、控制面板→管理工具→Internet信息服务&#xff08;IIS&…

一篇文章带你搞懂什么是DevOps?

DevOps DevOps 它的英文发音是 /de’vɒps/&#xff0c;类似于“迪沃普斯”&#xff0c;一词本身是对于 development 以及 operation 两个词的混合&#xff0c;其目的在于缩短系统开发的生命周期&#xff0c;在这过程中发布特性、修复bug以及更新均被紧密的结合。 简化的含义为…

微服务架构下分布式事务解决方案 —— 阿里GTS

1 微服务的发展 微服务倡导将复杂的单体应用拆分为若干个功能简单、松耦合的服务&#xff0c;这样可以降低开发难度、增强扩展性、便于敏捷开发。当前被越来越多的开发者推崇&#xff0c;很多互联网行业巨头、开源社区等都开始了微服务的讨论和实践。Hailo有160个不同服务构成&…

重要消息丨.NET Core 3.1 将于今年12月13日结束支持

点击上方蓝字关注我们&#xff08;本文阅读时间&#xff1a;5分钟).NET Core 3.1 将于 2022 年 12 月 13 日结束支持。此后&#xff0c;Microsoft 将不再为 .NET Core 3.1 提供服务更新或技术支持。我们建议尽快迁移到 .NET 6。如果您在支持日期结束后仍在使用 .NET Core 3.1&a…

产品设计的三大原则

1.它有用吗? 如果我们必须从这三个特性中选择一个作为最重要的&#xff0c;那就是有用性。 首要的是&#xff0c;一个产品必须有用。如果它无用&#xff0c;其它任何东西都是不相关的&#xff0c;因为没有人会需要它。很明显&#xff0c;有用性和可享用性看上去一样重要&#…

常用的17个运维监控系统

1. Zabbix Zabbix 作为企业级的网络监控工具&#xff0c;通过从服务器&#xff0c;虚拟机和网络设备收集的数据提供实时监控&#xff0c;自动发现&#xff0c;映射和可扩展等功能。 Zabbix的企业级监控软件为用户提供内置的Java应用服务器监控&#xff0c;硬件监控&#xff0c…

关于html-三角的制作

因为最近看到别人写的不错的样式&#xff0c;所以就想自己实现&#xff0c;但是呢用到了一个三角形&#xff0c;所以稍微研究一下。效果是这样的&#xff1a;注意是下边那个浅色三角&#xff0c;感觉书签的效果有木有。看着很有层次感。接下来就是实现了&#xff0c;利用border…

ABP中的数据过滤器

本文首先介绍了ABP内置的软删除过滤器(ISoftDelete)和多租户过滤器(IMultiTenant)&#xff0c;然后介绍了如何实现一个自定义过滤器&#xff0c;最后介绍了在软件开发过程中遇到的实际问题&#xff0c;同时给出了解决问题的一个未必最优的思路。一.预定义过滤器ABP中的数据过滤…

ActiveMQ与spring整合

2019独角兽企业重金招聘Python工程师标准>>> 1 生产者 第一步&#xff1a;引用相关的jar包。 <dependency> <groupId>org.springframework</groupId><artifactId>spring-jms</artifactId> </dependency> <dependency><…