具有动态 Brush 属性的 DrawingBrush.GeometryDrawing [英] DrawingBrush.GeometryDrawing with dynamic Brush property
问题描述
我正在尝试通过设置 DynamicResource
动态更改 DrawingBrush
内的 GeometryDrawing
的 Brush
.
I'm trying to dynamically change the Brush
of a GeometryDrawing
inside a DrawingBrush
by setting a 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>
当我更改应用程序的配色方案时,我将 ResourceDictionary
的顺序通过 Remove()
和 Insert()
移动到MergedDictionary
:
When I change the color scheme of my app, I shift the ordering of my ResourceDictionary
by Remove()
and Insert()
in the MergedDictionary
:
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
:
For example, inside the Light.xaml
, I have a SolidColorBrush
:
<SolidColorBrush x:Key="Element.Glyph.Strong" Color="#FF231F20"/>
在 App.xaml
里面,我导入了我的两个资源字典(顺序无关紧要,因为资源会被移到最后一个位置):
Inside the App.xaml
, I import both my resource dictionaries (the order does not matter, since the resources will be shifted to the last position):
<!--Themes-->
<ResourceDictionary Source="/Themes/Colors/Dark.xaml"/>
<ResourceDictionary Source="/Themes/Colors/Light.xaml"/>
<ResourceDictionary Source="/Resources/Vectors.xaml"/>
<ResourceDictionary Source="/Themes/Button.xaml"/>
矢量用作自定义 Button
上的图标.按钮内部有一个带大小和对齐的边框,矢量用作背景
.
The vector is used as an icon on a custom Button
. Inside the button there's a Border with a sizing and alignment, and the vector is used as the Background
.
Button
定义和用法(Icon
是一个 Brush
DependencyProperty
):
Button
definition and usage (Icon
is a 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
,作为测试.但是还是不行.
I was setting the Icon
as a StaticResource
, but I changed to DynamicResource
before asking in here, as a test. But it still didn't work.
这是按钮的简化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
不会更新.
只有在关闭应用程序并再次打开时才会显示具有正确颜色的矢量,因为它加载了新主题.
Only when closing the app and opening again will display the vector with the correct color, since it loads with the new theme.
我猜测 Brush
属性,作为 DependencyProperty
会在资源更新时更新.
I guessed that the Brush
property, as a DependencyProperty
would update when the resource updated too.
我想知道如何为 Brush
设置动态颜色,而不必使用背后的代码?
I wonder how could I set the Brush
with a dynamic color, without having to work with code behind?
推荐答案
我不确定您是如何更改主题的,但如果其他组件正在更改,那么我假设您的操作是正确的.
I'm not sure exactly how you are changing themes, but if other components are changing then I am assuming you are doing that correctly.
我认为关键是确保您使用的是 Background="{DynamicResource Vector.Close}"
而不是 Background="{StaticResource Vector.Close}";代码>.
I think the key is to make sure you are using Background="{DynamicResource Vector.Close}"
instead of 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);
}
显然这有点凌乱和笨拙,但它有效:
Obviously this is a little messy and hacky, but it works:
即使使用自定义样式,我也无法重现.这是切换后的样子:
I am not able to reproduce even when using the custom styling. Here it is after switching:
这篇关于具有动态 Brush 属性的 DrawingBrush.GeometryDrawing的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!