我正在尝试通过设置Brush来动态更改DrawingBrush中的GeometryDrawing的DynamicResource。
<DrawingBrush x:Key="Vector.Close" Stretch="Uniform" AlignmentX="Center" AlignmentY="Center">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="{DynamicResource Element.Glyph.Strong}" Geometry="F1 M 38.199,40 L 0,1.801 L 1.801,0 L 40,38.199 L 38.199,40 Z"/>
<GeometryDrawing Brush="{DynamicResource Element.Glyph.Strong}" Geometry="F1 M 1.801,40 L 0,38.199 L 38.199,0 L 40,1.801 L 1.801,40 Z"/>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>当我更改应用程序的配色方案时,我会在MergedDictionary中通过Remove()和Insert()改变ResourceDictionary的顺序
public static void SelectTheme(string id = "Light")
{
var theme = Application.Current.Resources.MergedDictionaries.FirstOrDefault(f => f.Source != null && f.Source.ToString().EndsWith($"Colors/{id}.xaml"));
if (theme == null)
{
theme = Application.Current.Resources.MergedDictionaries.FirstOrDefault(f => f.Source != null && f.Source.ToString().EndsWith("Colors/Light.xaml"));
UserSettings.All.MainTheme = AppTheme.Light;
}
Application.Current.Resources.MergedDictionaries.Remove(theme);
Application.Current.Resources.MergedDictionaries.Add(theme);
}例如,在Light.xaml中,我有一个SolidColorBrush
<SolidColorBrush x:Key="Element.Glyph.Strong" Color="#FF231F20"/>在App.xaml中,我导入了两个资源字典(顺序并不重要,因为资源将被移到最后一个位置):
<!--Themes-->
<ResourceDictionary Source="/Themes/Colors/Dark.xaml"/>
<ResourceDictionary Source="/Themes/Colors/Light.xaml"/>
<ResourceDictionary Source="/Resources/Vectors.xaml"/>
<ResourceDictionary Source="/Themes/Button.xaml"/>该向量用作自定义Button上的图标。在按钮内部有一个带有大小和对齐方式的边框,向量用作Background。
Button定义和用法(Icon是Brush DependencyProperty):
public class ExtendedButton : Button
{
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(nameof(Icon), typeof(Brush), typeof(ExtendedButton));
public Brush Icon
{
get => (Brush)GetValue(IconProperty);
set => SetCurrentValue(IconProperty, value);
}
//Ctor and other stuff.
}
<n:ExtendedButton Style="{DynamicResource Style.Button.NoText}"
Icon="{DynamicResource Vector.Close}" Width="30" Padding="6"/>我将Icon设置为StaticResource,但作为测试,我在询问之前更改为DynamicResource。但它仍然不起作用。
下面是按钮的简化Style:
<!--Button • No Border • No Text-->
<Style TargetType="{x:Type n:ExtendedButton}" BasedOn="{StaticResource {x:Type Button}}" x:Key="Style.Button.NoText">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type n:ExtendedButton}">
<Border x:Name="MainBorder" MinHeight="{TemplateBinding MinHeight}" Background="{TemplateBinding Background}">
<Grid x:Name="InnerGrid">
<Border Background="{TemplateBinding Icon}" Margin="{TemplateBinding Padding}" Opacity="{DynamicResource Element.Opacity}"
Height="14" Width="14" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource Brush.Button.Background.Hover}"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{DynamicResource Brush.Button.Background.Pressed}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.7"/>
</Trigger>
</Style.Triggers>
</Style>应用程序的其余部分可以正常工作,当改变主题时,其他一切都会改变。GeometryDrawing中的Element.Glyph.Strong不会更新。
只有当关闭应用程序并再次打开时,才会以正确的颜色显示矢量,因为它加载了新的主题。
我猜测作为DependencyProperty的Brush属性也会随着资源的更新而更新。
我想知道如何才能将Brush设置为动态颜色,而不必使用后面的代码?
发布于 2020-09-12 03:43:03
我不确定您是如何更改主题的,但如果其他组件正在更改,那么我假设您这样做是正确的。
我认为关键是要确保你使用的是Background="{DynamicResource Vector.Close}"而不是Background="{StaticResource Vector.Close}"。
Dictionary1.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp1">
<SolidColorBrush x:Key="Element.Glyph.Strong" Color="Black" />
</ResourceDictionary>Dictionary2.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp1">
<SolidColorBrush x:Key="Element.Glyph.Strong" Color="Yellow" />
</ResourceDictionary>Dictionary3.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp1">
<DrawingBrush x:Key="Vector.Close" Stretch="Uniform" AlignmentX="Center" AlignmentY="Center">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="{DynamicResource Element.Glyph.Strong}" Geometry="F1 M 38.199,40 L 0,1.801 L 1.801,0 L 40,38.199 L 38.199,40 Z"/>
<GeometryDrawing Brush="{DynamicResource Element.Glyph.Strong}" Geometry="F1 M 1.801,40 L 0,38.199 L 38.199,0 L 40,1.801 L 1.801,40 Z"/>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</ResourceDictionary>MainWindow.xaml
<Window x:Class="WpfApp1.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:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Button Background="{DynamicResource Vector.Close}" Width="40" Height="40" VerticalAlignment="Center" Click="ChangeTheme_Click" HorizontalAlignment="Center"/>
</Grid>
</Window>MainWindow.xaml.cs
// stuff up here...
public string currentDict = "Dictionary1.xaml";
private void ChangeTheme_Click(object sender, RoutedEventArgs e)
{
if (currentDict == "Dictionary1.xaml")
{
currentDict = "Dictionary2.xaml";
} else
{
currentDict = "Dictionary1.xaml";
}
var app = (App)Application.Current;
app.ChangeTheme(new Uri(currentDict, UriKind.RelativeOrAbsolute));
}App.xaml
<Application x:Class="WpfApp1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp1"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" />
<ResourceDictionary Source="Dictionary3.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>App.xaml.cs
public void ChangeTheme(Uri uri)
{
var dict = new ResourceDictionary() { Source = uri };
var dict2 = new ResourceDictionary() { Source = new Uri("Dictionary3.xaml", UriKind.RelativeOrAbsolute) };
Resources.MergedDictionaries.Clear();
Resources.MergedDictionaries.Add(dict);
Resources.MergedDictionaries.Add(dict2);
}显然,这有点麻烦,但它是有效的:


编辑:
即使使用自定义样式,我也无法重现。这是切换后的结果:

https://stackoverflow.com/questions/63852845
复制相似问题