我正在尝试动态更改画笔的颜色。我写了一个非常简单的例子,但我不明白为什么它不起作用。
我在我的应用程序的ResourceDictionary中定义了一个前景色和一个使用该颜色作为DynamicResource的前景画笔:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Color x:Key="Foreground">#FF0000</Color>
<SolidColorBrush x:Key="ForegroundBrush" Color="{DynamicResource Foreground}" />
</ResourceDictionary>
然后,在我的Window.xaml中,我使用画笔设置文本块前景:
<Window x:Class="DictionaryColorTests.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel>
<TextBlock Name="mTextBlock" Foreground="{DynamicResource ForegroundBrush}">This is just a text block</TextBlock>
<Button Name="Button1" Click="Button1_Click">Change color</Button>
</StackPanel>
</Grid>
</Window>
最后在我的代码背后,我正在改变颜色:
private void Button1_Click(object sender, RoutedEventArgs e)
{
Application.Current.Resources["Foreground"] = Colors.Green;
}
不幸的是,刷子颜色没有更新。有人可以解释原因吗?
注意:我知道如果我直接更改它的工作颜色很好,但我试图理解为什么使用颜色作为动态资源的SolidColorBrush不会更新它颜色变化时的颜色。
更新:如果我使用文本块的样式,只更新颜色,它工作正常,刷子采用正确的颜色。直接使用画笔或使用样式有什么区别?
<Style TargetType="TextBlock" x:Key="TextBlockStyle">
<Setter Property="Foreground" Value="{StaticResource ForegroundBrush}" />
</Style>
答案 0 :(得分:2)
如果没有可靠地再现您的问题的好Minimal, Complete, and Verifiable code example,就无法确定问题是什么。但基本问题似乎是您试图以不受支持的方式使用DynamicResource
。
动态资源引用有一些值得注意的限制。必须至少满足下列条件之一:
•要设置的属性必须是FrameworkElement或FrameworkContentElement上的属性。该属性必须由DependencyProperty支持。
•引用是针对StyleSetter中的值。
•正在设置的属性必须是Freezable上的属性,该属性作为FrameworkElement或FrameworkContentElement属性或Setter值的值提供。
由于要设置的属性必须是DependencyProperty或Freezable属性,因此大多数属性更改都可以传播到UI,因为属性系统会确认属性更改(更改的动态资源值)。如果DependencyProperty发生更改并且该属性可能影响布局,则大多数控件都包含将强制控件的另一个布局的逻辑。但是,并非所有将DynamicResource标记扩展作为其值的属性都可以保证以在UI中实时更新的方式提供值 [强调我的] 。该功能仍可能因属性而异,具体取决于拥有该属性的类型,甚至应用程序的逻辑结构。
您要在SolidColorBrush
对象上设置属性,该对象不为FrameworkElement
或FrameworkContentElement
。方案 虽然符合文档中的第三个项目符号点(SolidColorBrush
是Freezable
,而Freezable
是作为{FrameworkElement
的值提供的1}})。但请注意我加粗的文字。即使满足这些要求,也不能保证它会起作用。
有趣的是,当您在ResourceDictionary
直接拥有的FrameworkElement
的上下文中完成时,您似乎尝试实施的基本方法可以正常工作(例如Window
)。
为什么会这样,我不知道。我的猜测是,只要您处于FrameworkElement
某处的上下文中,就有足够的内部状态管理来处理更新DynamicResource
个代理,所以它让它工作。
无论如何,这意味着一种可能的解决方法是将您的资源放入Window.Resources
而不是现在放置它们的任何地方。我不知道你可以指望总是工作;毕竟,文档中包含的内容可以让微软说出来,也许它会起作用,也许它会赢得“不可能”。但在我看来,这似乎不是一个很快就会被打破的情景。
或者,您可以修改画笔资源本身。 E.g:
private void Button1_Click(object sender, RoutedEventArgs e)
{
Application.Current.Resources["ForegroundBrush"] = new SolidColorBrush(Colors.Green);
}
符合文档中的更多要求,因此更有可能适用于任何未来版本的.NET(我已经证实它今天可以正常工作)。
答案 1 :(得分:0)
我认为这是唯一的原因,Color是一种值类型的数据,当你从ResourceDictionary获得一个源时,它返回Color的值(副本),重新分配的动作不会影响到原始实例(资源)。 所以认为可以有很多解决方案来解决这个问题:
this.Resources["ForegroundBrush"] = new SolidColorBrush(Colors.Green);
Or
var brush = this.Resources["ForegroundBrush"] as SolidColorBrush;
if(brush != null){
brush.Color = Colors.Green;
}