运行时覆盖引用DLL中SolidColorBrush资源的UI更新问题
解决WPF运行时覆盖DLL中SolidColorBrush资源不生效的问题
问题原因
核心问题在于DLL中的资源字典默认作为合并字典加载到应用资源中,且资源对象(如SolidColorBrush、Color)通常会被冻结(Freezable)以优化性能。直接在Application.Current.Resources根字典中添加同名资源时,可能因资源查找优先级、冻结状态或加载顺序问题,导致控件的DynamicResource绑定仍引用原始资源。
解决方案
方案1:直接修改DLL资源字典中的原始资源
最可靠的方式是定位到DLL加载的资源字典实例,直接修改其中的资源,确保DynamicResource绑定能感知到变化:
// 定位到MyStyle.dll中的Styling.xaml资源字典 var stylingDict = Application.Current.Resources.MergedDictionaries .FirstOrDefault(d => d.Source?.ToString().Contains("MyStyle;component/Styling.xaml") == true); if (stylingDict != null) { // 定位到其合并的Colors.xaml字典 var colorsDict = stylingDict.MergedDictionaries .FirstOrDefault(d => d.Source?.ToString().EndsWith("Colors/Colors.xaml") == true); if (colorsDict != null) { // 方式1:修改MyColor,MyBrush会自动更新(因为MyBrush绑定了DynamicResource MyColor) colorsDict["MyColor"] = Colors.Aqua; // 方式2:直接替换MyBrush(如果不需要关联MyColor的变化) // colorsDict["MyBrush"] = new SolidColorBrush(Colors.Aqua); } }
方案2:确保覆盖资源的优先级高于DLL资源
如果希望在应用根资源中覆盖,可创建新的资源字典并插入到合并字典集合的最前面,确保查找时优先命中覆盖资源:
var overrideDict = new ResourceDictionary(); overrideDict["MyBrush"] = Brushes.Aqua; // 将覆盖字典插入到合并字典的首位,提升查找优先级 Application.Current.Resources.MergedDictionaries.Insert(0, overrideDict);
方案3:检查资源加载与合并代码
确认你正确将DLL资源字典合并到应用资源中,而非直接替换Application.Resources:
// 正确的合并方式 var stylingDict = LoadComponent(new Uri("/MyStyle;v7.0.0.0;3d70d0e64510241c;component/Styling.xaml", UriKind.Relative)) as ResourceDictionary; if (stylingDict != null) { Application.Current.Resources.MergedDictionaries.Add(stylingDict); }
若之前是直接赋值Application.Current.Resources = stylingDict;,则修改Application.Current.Resources["MyBrush"]应直接生效。若仍无效,检查资源是否被冻结:
var originalBrush = Application.Current.Resources["MyBrush"] as SolidColorBrush; if (originalBrush != null && originalBrush.IsFrozen) { // 冻结资源无法修改,需创建新实例替换 var newBrush = new SolidColorBrush(originalBrush.Color); Application.Current.Resources["MyBrush"] = newBrush; newBrush.Color = Colors.Aqua; }
内容的提问来源于stack exchange,提问作者Relaxo
相关产品推荐
相关产品推荐

