c# - 使用 WPF 为多个动态皮肤字典创建别名颜色定义
问题描述
我正在尝试在大型 WPF 应用程序中设置主题框架。目前我们找到的解决方案是为每个调色板创建单独的 .xaml 文件,如下所示:
<LightColors.xaml>
<Color x:Key="MainPanelColor">Aqua</Color>
<Color x:Key="MainItemColor">Orange</Color>
<SolidColorBrush x:Key="MainPanelBrush" Color="{StaticResource MainPanelColor}" />
<SolidColorBrush x:Key="MainItemBrush" Color="{StaticResource MainItemColor}" />
UI 然后像这样引用这些项目:
<Textblock Foreground="{DynamicResource MainItemBrush}"/>
调色板在 C# 运行时更改。这个主题框架完成了允许在运行时更改主题的任务。
问题:我想在 UI 和颜色之间创建一个图层,以便调色板颜色可以链接到整个 UI 中使用的大量颜色定义列表。我发现接近工作的唯一解决方案是添加这样的文件:
<ColorDefinitions.xaml>
<DynamicResource x:Key="Textblock_SetupPage_Foreground" ResourceKey="MainItemBrush" />
<DynamicResource x:Key="SecondDefinition" ResourceKey="MainItemBrush" />
并像这样在 UI 中引用这个新资源:
<Textblock Foreground="{StaticResource Textblock_SetupPage_Foreground}" />
但是,此解决方案并不完全有效。它只允许单个 UI 元素使用 DynamicResource 之一,例如“Textblock_SetupPage_Foreground”,并且将 Textblock 引用更改为 DynamicResource 会产生错误。我怎样才能完成这项任务?
解决方案
不太确定这是否能解决您的问题,但我可以向您展示如何在我们的 LOB 中实现蒙皮。示例解决方案由两个程序集和示例应用程序组成。
MyCustomControlLibrary 定义颜色和画笔以及一个示例自定义控件。颜色和画笔可以进一步分离成一个额外的组件。
MySkinsLibrary 定义皮肤并使用来自 MyControlLibrary 的定义(资源)。
WpfSkinTestApp 使用皮肤并间接使用 MyCostumControlLibrary。
颜色.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyCustomControlLibrary">
<Color x:Key="MyDarkColor">#FF123456</Color>
<Color x:Key="MyLightColor">#FF456789</Color>
<Color x:Key="MyNeutralColor">#FF666666</Color>
画笔.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyCustomControlLibrary">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MyCustomControlLibrary;component/ResourceDictionaries/Colors.xaml"/>
</ResourceDictionary.MergedDictionaries>
<SolidColorBrush x:Key="MyDarkColorBrush" Color="{StaticResource MyDarkColor}"/>
<SolidColorBrush x:Key="MyLightColorBrush" Color="{StaticResource MyLightColor}"/>
<SolidColorBrush x:Key="MyNeutralColorBrush" Color="{StaticResource MyNeutralColor}"/>
通用的.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyCustomControlLibrary">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MyCustomControlLibrary;component/ResourceDictionaries/Brushes.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type local:MyCustomControl}">
<Setter Property="Background" Value="{StaticResource MyNeutralColorBrush}"/>
<Setter Property="BorderBrush" Value="White"/>
<Setter Property="BorderThickness" Value="6"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyCustomControl}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
DarkSkin.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MySkinsLibrary.Skins"
xmlns:customControls="clr-namespace:MyCustomControlLibrary;assembly=MyCustomControlLibrary">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MyCustomControlLibrary;component/Themes/Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="MyTextBlockStyle" TargetType="TextBlock">
<Setter Property="Background" Value="Gray"/>
<Setter Property="Foreground" Value="{StaticResource MyDarkColorBrush}"/>
</Style>
<Style x:Key="MyCustomControlStyle" TargetType="{x:Type customControls:MyCustomControl}" BasedOn="{StaticResource {x:Type customControls:MyCustomControl}}">
<Setter Property="Background" Value="{StaticResource MyDarkColorBrush}"/>
</Style>
LightSkin.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MySkinsLibrary.Skins"
xmlns:customControls="clr-namespace:MyCustomControlLibrary;assembly=MyCustomControlLibrary">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MyCustomControlLibrary;component/Themes/Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="MyTextBlockStyle" TargetType="TextBlock">
<Setter Property="Background" Value="Gray"/>
<Setter Property="Foreground" Value="{StaticResource MyLightColorBrush}"/>
</Style>
<Style x:Key="MyCustomControlStyle" TargetType="{x:Type customControls:MyCustomControl}" BasedOn="{StaticResource {x:Type customControls:MyCustomControl}}">
<Setter Property="Background" Value="{StaticResource MyLightColorBrush}"/>
</Style>
在您的应用程序中,您可以使用 app.xaml 中的不同外观,如下所示:(出于设计目的)
<Application x:Class="WpfSkinTestApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfSkinTestApp"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MySkinsLibrary;component/Skins/LightSkin.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
并在运行时更改它,例如:
private void RadioButton_Checked(object sender, RoutedEventArgs e)
{
string skinName = "LightSkin";
if (((RadioButton)sender).Name == "DarkSkin")
{
skinName = "DarkSkin";
}
ResourceDictionary resources = new ResourceDictionary();
resources.Source = new Uri($"pack://application:,,,/MySkinsLibrary;component/Skins/{skinName}.xaml");
Application.Current.Resources = resources;
}
为了完整起见,这是测试应用程序的主窗口:
<Window x:Class="WpfSkinTestApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:customControls="clr-namespace:MyCustomControlLibrary;assembly=MyCustomControlLibrary"
xmlns:local="clr-namespace:WpfSkinTestApp"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
Background="{StaticResource MyNeutralColorBrush}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="1"
Grid.Row="1"
Text="Example Colors"
Style="{DynamicResource MyTextBlockStyle}"/>
<customControls:MyCustomControl Grid.Column="1"
Grid.Row="2"
Style="{DynamicResource MyCustomControlStyle}"/>
<StackPanel Grid.Column="2"
Grid.Row="2"
Margin="24" >
<RadioButton x:Name="LightSkin" GroupName="1" Content="Light Skin" IsChecked="True" Checked="RadioButton_Checked"/>
<RadioButton x:Name="DarkSkin" GroupName="1" Content="Dark Skin" Checked="RadioButton_Checked"/>
</StackPanel>
</Grid>
让我知道,如果这是你要找的。
推荐阅读
- javascript - Odoo 13 Enterprise SaaS,我可以编辑产品搜索模块以仅使用 JavaScript 搜索产品描述吗?
- selenium - Selenium Python 从表格行中获取数据
- python - Flask 访问 json 数据并将其嵌入到标签中
- javascript - 汇总没有特定键名的数据
- java - 使用 fluentbit 从 Kubernetes 中的 Java 消息中删除颜色代码
- r - R 创建带有日期和版本号的子文件夹(如果不存在)并增加版本号(如果存在)
- c# - 如何编辑环境变量,bash:dotnet:找不到命令?
- c# - 根据创建日期从列表中删除旧文件
- python - 逻辑回归预测 30% 的响应而不是预期的 6%
- service-worker - 在 service worker 更新通知中,是否有可能知道关于等待安装的新版本的任何信息?