Z L*_*ang 5 c# wpf xaml themes dynamicresource
我正在尝试在大型 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}" />
Run Code Online (Sandbox Code Playgroud)
然后 UI 会像这样引用这些项目:
<Textblock Foreground="{DynamicResource MainItemBrush}"/>
Run Code Online (Sandbox Code Playgroud)
在 C# 中,调色板在运行时会更改。该主题框架完成了允许在运行时更改主题的任务。
问题:我想在 UI 和颜色之间创建一个层,以便调色板颜色可以链接到整个 UI 中使用的大量颜色定义。我发现接近有效的唯一解决方案是添加如下文件:
<ColorDefinitions.xaml>
<DynamicResource x:Key="Textblock_SetupPage_Foreground" ResourceKey="MainItemBrush" />
<DynamicResource x:Key="SecondDefinition" ResourceKey="MainItemBrush" />
Run Code Online (Sandbox Code Playgroud)
并在 UI 中引用这个新资源,如下所示:
<Textblock Foreground="{StaticResource Textblock_SetupPage_Foreground}" />
Run Code Online (Sandbox Code Playgroud)
不过,这个解决方案并不能完全发挥作用。它只允许单个 UI 元素使用 DynamicResources 之一,例如“Textblock_SetupPage_Foreground”,并且将 Textblock 引用更改为 DynamicResource 会产生错误。我怎样才能完成这个任务?
小智 2
不太确定这是否能解决您的问题,但我可以向您展示如何在 LOB 中实现换肤。该示例解决方案由两个程序集和示例应用程序组成。
\n\nMyCustomControlLibrary 定义颜色和画笔以及示例自定义控件。颜色和画笔可以进一步分离为额外的组件。
\n\nMySkinsLibrary 定义外观并使用 MyControlLibrary 中的定义(资源)。
\n\nWpfSkinTestApp 使用皮肤并间接使用 MyCostumControlLibrary。
\n\n\n\n颜色.xaml:
\n\n<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\n xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\n xmlns:local="clr-namespace:MyCustomControlLibrary">\n<Color x:Key="MyDarkColor">#FF123456</Color>\n<Color x:Key="MyLightColor">#FF456789</Color>\n<Color x:Key="MyNeutralColor">#FF666666</Color>\n
Run Code Online (Sandbox Code Playgroud)\n\n\n\n画笔.xaml
\n\n<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\n xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\n xmlns:local="clr-namespace:MyCustomControlLibrary">\n<ResourceDictionary.MergedDictionaries>\n <ResourceDictionary Source="/MyCustomControlLibrary;component/ResourceDictionaries/Colors.xaml"/>\n</ResourceDictionary.MergedDictionaries>\n<SolidColorBrush x:Key="MyDarkColorBrush" Color="{StaticResource MyDarkColor}"/>\n<SolidColorBrush x:Key="MyLightColorBrush" Color="{StaticResource MyLightColor}"/>\n<SolidColorBrush x:Key="MyNeutralColorBrush" Color="{StaticResource MyNeutralColor}"/>\n
Run Code Online (Sandbox Code Playgroud)\n\n\n\n通用.xaml
\n\n<ResourceDictionary\nxmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\nxmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\nxmlns:local="clr-namespace:MyCustomControlLibrary">\n<ResourceDictionary.MergedDictionaries>\n <ResourceDictionary Source="/MyCustomControlLibrary;component/ResourceDictionaries/Brushes.xaml"/>\n</ResourceDictionary.MergedDictionaries>\n<Style TargetType="{x:Type local:MyCustomControl}">\n <Setter Property="Background" Value="{StaticResource MyNeutralColorBrush}"/>\n <Setter Property="BorderBrush" Value="White"/>\n <Setter Property="BorderThickness" Value="6"/>\n <Setter Property="Template">\n <Setter.Value>\n <ControlTemplate TargetType="{x:Type local:MyCustomControl}">\n <Border Background="{TemplateBinding Background}"\n BorderBrush="{TemplateBinding BorderBrush}"\n BorderThickness="{TemplateBinding BorderThickness}">\n\n </Border>\n </ControlTemplate>\n </Setter.Value>\n </Setter>\n</Style>\n
Run Code Online (Sandbox Code Playgroud)\n\n\n\n深色皮肤.xaml
\n\n<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\n xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\n xmlns:local="clr-namespace:MySkinsLibrary.Skins"\n xmlns:customControls="clr-namespace:MyCustomControlLibrary;assembly=MyCustomControlLibrary">\n<ResourceDictionary.MergedDictionaries>\n <ResourceDictionary Source="/MyCustomControlLibrary;component/Themes/Generic.xaml"/>\n</ResourceDictionary.MergedDictionaries>\n\n<Style x:Key="MyTextBlockStyle" TargetType="TextBlock">\n <Setter Property="Background" Value="Gray"/>\n <Setter Property="Foreground" Value="{StaticResource MyDarkColorBrush}"/>\n</Style>\n\n<Style x:Key="MyCustomControlStyle" TargetType="{x:Type customControls:MyCustomControl}" BasedOn="{StaticResource {x:Type customControls:MyCustomControl}}">\n <Setter Property="Background" Value="{StaticResource MyDarkColorBrush}"/>\n</Style>\n
Run Code Online (Sandbox Code Playgroud)\n\n\n\nLightSkin.xaml
\n\n<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\n xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\n xmlns:local="clr-namespace:MySkinsLibrary.Skins"\n xmlns:customControls="clr-namespace:MyCustomControlLibrary;assembly=MyCustomControlLibrary">\n<ResourceDictionary.MergedDictionaries>\n <ResourceDictionary Source="/MyCustomControlLibrary;component/Themes/Generic.xaml"/>\n</ResourceDictionary.MergedDictionaries>\n\n<Style x:Key="MyTextBlockStyle" TargetType="TextBlock">\n <Setter Property="Background" Value="Gray"/>\n <Setter Property="Foreground" Value="{StaticResource MyLightColorBrush}"/>\n</Style>\n\n<Style x:Key="MyCustomControlStyle" TargetType="{x:Type customControls:MyCustomControl}" BasedOn="{StaticResource {x:Type customControls:MyCustomControl}}">\n <Setter Property="Background" Value="{StaticResource MyLightColorBrush}"/>\n</Style>\n
Run Code Online (Sandbox Code Playgroud)\n\n\n\n在您的应用程序中,您可以在 app.xaml 中使用不同的外观,如下所示:\n(出于设计目的)
\n\n<Application x:Class="WpfSkinTestApp.App"\n xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\n xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\n xmlns:local="clr-namespace:WpfSkinTestApp"\n StartupUri="MainWindow.xaml">\n<Application.Resources>\n <ResourceDictionary>\n <ResourceDictionary.MergedDictionaries>\n <ResourceDictionary Source="pack://application:,,,/MySkinsLibrary;component/Skins/LightSkin.xaml"/>\n </ResourceDictionary.MergedDictionaries>\n </ResourceDictionary>\n</Application.Resources>\n
Run Code Online (Sandbox Code Playgroud)\n\n\n\n并在运行时更改它,例如这样:
\n\nprivate void RadioButton_Checked(object sender, RoutedEventArgs e)\n {\n string skinName = "LightSkin";\n\n if (((RadioButton)sender).Name == "DarkSkin")\n {\n skinName = "DarkSkin";\n }\n\n ResourceDictionary resources = new ResourceDictionary();\n resources.Source = new Uri($"pack://application:,,,/MySkinsLibrary;component/Skins/{skinName}.xaml");\n Application.Current.Resources = resources;\n }\n
Run Code Online (Sandbox Code Playgroud)\n\n为了完整性,这是测试应用程序的主窗口:
\n\n<Window x:Class="WpfSkinTestApp.MainWindow"\n xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\n xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\n xmlns:d="http://schemas.microsoft.com/expression/blend/2008"\n xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"\n xmlns:customControls="clr-namespace:MyCustomControlLibrary;assembly=MyCustomControlLibrary"\n xmlns:local="clr-namespace:WpfSkinTestApp"\n mc:Ignorable="d"\n Title="MainWindow" Height="350" Width="525"\n Background="{StaticResource MyNeutralColorBrush}">\n<Grid>\n <Grid.ColumnDefinitions>\n <ColumnDefinition/>\n <ColumnDefinition/>\n <ColumnDefinition/>\n </Grid.ColumnDefinitions>\n <Grid.RowDefinitions>\n <RowDefinition/>\n <RowDefinition Height="Auto"/>\n <RowDefinition/>\n <RowDefinition/>\n </Grid.RowDefinitions>\n <TextBlock Grid.Column="1"\n Grid.Row="1"\n Text="Example Colors"\n Style="{DynamicResource MyTextBlockStyle}"/>\n <customControls:MyCustomControl Grid.Column="1"\n Grid.Row="2"\n Style="{DynamicResource MyCustomControlStyle}"/>\n <StackPanel Grid.Column="2"\n Grid.Row="2"\n Margin="24" >\n <RadioButton x:Name="LightSkin" GroupName="1" Content="Light Skin" IsChecked="True" Checked="RadioButton_Checked"/>\n <RadioButton x:Name="DarkSkin" GroupName="1" Content="Dark Skin" Checked="RadioButton_Checked"/>\n </StackPanel>\n</Grid>\n
Run Code Online (Sandbox Code Playgroud)\n\n\n\n如果这就是您\xc2\xb4 正在寻找的东西,请告诉我。
\n