You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF:绑定DynamicResource的DrawingImage主题切换不更新如何修复?

问题

我定义了一个DrawingImage资源,其画刷颜色通过DynamicResource绑定到Image.FillColor,代码如下:

<DrawingImage x:Key="img_building">
    <DrawingImage.Drawing>
        <DrawingGroup ClipGeometry="M0,0 V512 H512 V0 H0 Z">
            <DrawingGroup Opacity="1">
                <GeometryDrawing Geometry="F1 M512,512z M0,0z M256.5,17.2L512,119.4 512,153.8 477.6,153.8C477.6,158.4 475.7,162.2 472,165.9 468.3,169.6 463.6,170.5 459,170.5L53,170.5C48.4,170.5 43.7,168.6 40,165.9 36.3,163.1 34.4,158.5 34.4,153.8L0,153.8 0,119.4 256.5,17.2z M68.8,188.2L136.6,188.2 136.6,392.6 171,392.6 171,188.2 238.8,188.2 238.8,392.6 273.2,392.6 273.2,188.2 341,188.2 341,392.6 375.4,392.6 375.4,188.2 443.2,188.2 443.2,392.6 459,392.6C463.6,392.6 468.3,394.5 472,397.2 475.7,400 477.6,404.6 477.6,409.3L477.6,426 35.3,426 35.3,409.3C35.3,404.7 37.2,400.9 40.9,397.2 44.6,393.5 49.3,392.6 53.9,392.6L69.7,392.6 69.7,188.2 68.8,188.2z M493.4,443.7C498,443.7 502.7,445.6 506.4,448.3 510.1,452 512,455.7 512,460.4L512,494.8 0.9,494.8 0.9,460.4C0.9,455.8 2.8,452 6.5,448.3 10.2,444.6 14.9,443.7 19.5,443.7L493.4,443.7z" >
                    <GeometryDrawing.Brush>
                        <SolidColorBrush Color="{DynamicResource Image.FillColor}" />
                    </GeometryDrawing.Brush>
                </GeometryDrawing>
            </DrawingGroup>
        </DrawingGroup>
    </DrawingImage.Drawing>
</DrawingImage>

接着在DataTemplate中引用该资源:

<DataTemplate x:Key="buildingImage">
    <WrapPanel>
        <WrapPanel.Resources>
            <Style TargetType="{x:Type Image}">
                <Setter Property="Margin" Value="0,0,4,0"></Setter>
                <Setter Property="MaxHeight" Value="20"></Setter>
            </Style>
        </WrapPanel.Resources>
        <Image Source="{DynamicResource img_building}" />
    </WrapPanel>
</DataTemplate>

程序运行正常,但切换应用主题时,Image.FillColor已变更,图像却未随之更新。推测该资源仅被渲染一次并重复使用,请问如何修复?能否通过后台代码强制重新加载DrawingImage?


解决方案

方法一:修改XAML实现动态更新

问题核心是DrawingImage不属于FrameworkElement,无法主动监听内部动态资源的变化。可以通过以下两种XAML调整解决:

1. 将DrawingImage移入DataTemplate内部

让每个模板实例创建独立的DrawingImage,主题切换时会重新解析资源:

<DataTemplate x:Key="buildingImage">
    <WrapPanel>
        <WrapPanel.Resources>
            <Style TargetType="{x:Type Image}">
                <Setter Property="Margin" Value="0,0,4,0"></Setter>
                <Setter Property="MaxHeight" Value="20"></Setter>
            </Style>
            <DrawingImage x:Key="img_building">
                <DrawingImage.Drawing>
                    <DrawingGroup ClipGeometry="M0,0 V512 H512 V0 H0 Z">
                        <DrawingGroup Opacity="1">
                            <GeometryDrawing Geometry="F1 M512,512z M0,0z M256.5,17.2L512,119.4 512,153.8 477.6,153.8C477.6,158.4 475.7,162.2 472,165.9 468.3,169.6 463.6,170.5 459,170.5L53,170.5C48.4,170.5 43.7,168.6 40,165.9 36.3,163.1 34.4,158.5 34.4,153.8L0,153.8 0,119.4 256.5,17.2z M68.8,188.2L136.6,188.2 136.6,392.6 171,392.6 171,188.2 238.8,188.2 238.8,392.6 273.2,392.6 273.2,188.2 341,188.2 341,392.6 375.4,392.6 375.4,188.2 443.2,188.2 443.2,392.6 459,392.6C463.6,392.6 468.3,394.5 472,397.2 475.7,400 477.6,404.6 477.6,409.3L477.6,426 35.3,426 35.3,409.3C35.3,404.7 37.2,400.9 40.9,397.2 44.6,393.5 49.3,392.6 53.9,392.6L69.7,392.6 69.7,188.2 68.8,188.2z M493.4,443.7C498,443.7 502.7,445.6 506.4,448.3 510.1,452 512,455.7 512,460.4L512,494.8 0.9,494.8 0.9,460.4C0.9,455.8 2.8,452 6.5,448.3 10.2,444.6 14.9,443.7 19.5,443.7L493.4,443.7z" >
                                <GeometryDrawing.Brush>
                                    <SolidColorBrush Color="{DynamicResource Image.FillColor}" />
                                </GeometryDrawing.Brush>
                            </GeometryDrawing>
                        </DrawingGroup>
                    </DrawingGroup>
                </DrawingImage.Drawing>
            </DrawingImage>
        </WrapPanel.Resources>
        <Image Source="{DynamicResource img_building}" />
    </WrapPanel>
</DataTemplate>

2. 给画刷设置x:Shared="False"

确保每次引用画刷都创建新实例,从而监听动态资源变化:

<!-- 先定义全局共享画刷 -->
<SolidColorBrush x:Key="ImageFillBrush" x:Shared="False" Color="{DynamicResource Image.FillColor}" />

<!-- 修改DrawingImage中的画刷引用 -->
<GeometryDrawing.Brush>
    <StaticResource ResourceKey="ImageFillBrush" />
</GeometryDrawing.Brush>

方法二:后台代码强制更新

如果需要保留全局DrawingImage资源,可在主题切换时手动刷新:

1. 直接更新画刷颜色并通知刷新

// 监听主题切换事件(根据你的应用实现,比如自定义ThemeChanged事件)
private void OnThemeChanged(object sender, EventArgs e)
{
    var drawingImage = (DrawingImage)Application.Current.Resources["img_building"];
    if (drawingImage == null) return;

    // 逐层获取内部的GeometryDrawing
    var rootGroup = (DrawingGroup)drawingImage.Drawing;
    var innerGroup = (DrawingGroup)rootGroup.Children[0];
    var geometryDrawing = (GeometryDrawing)innerGroup.Children[0];

    // 获取新颜色并更新画刷
    var newColor = (Color)Application.Current.TryFindResource("Image.FillColor");
    var brush = (SolidColorBrush)geometryDrawing.Brush;
    brush.Color = newColor;

    // 解除冻结并通知属性变更
    drawingImage.Freeze(false);
    drawingImage.InvalidateProperty(DrawingImage.DrawingProperty);
}

2. 重置Image的Source触发刷新

// 查找所有使用该资源的Image控件并重置Source
private void RefreshAllBuildingImages(DependencyObject parent)
{
    var targetResource = Application.Current.Resources["img_building"];
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
    {
        var child = VisualTreeHelper.GetChild(parent, i);
        if (child is Image image && image.Source == targetResource)
        {
            image.Source = null;
            image.Source = (DrawingImage)targetResource;
        }
        RefreshAllBuildingImages(child);
    }
}

// 主题切换时调用:RefreshAllBuildingImages(Application.Current.MainWindow);

内容的提问来源于stack exchange,提问作者Roni Tovi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 22:25:24