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>
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);
}
For example, inside the Light.xaml, I have a SolidColorBrush:
<SolidColorBrush x:Key="Element.Glyph.Strong" Color="#FF231F20"/>
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"/>
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 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"/>
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.
Here's the simplified Style for the button:
<!--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>
The rest of the app works, when changing the theme, everything else changes. The Element.Glyph.Strong inside the GeometryDrawing does not update.
Only when closing the app and opening again will display the vector with the correct color, since it loads with the new theme.
I guessed that the Brush property, as a DependencyProperty would update when the resource updated too.
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.
I think the key is to make sure you are using
Background="{DynamicResource Vector.Close}"instead ofBackground="{StaticResource Vector.Close}".Dictionary1.xamlDictionary2.xamlDictionary3.xamlMainWindow.xamlMainWindow.xaml.csApp.xamlApp.xaml.csObviously this is a little messy and hacky, but it works:
Edit:
I am not able to reproduce even when using the custom styling. Here it is after switching: