我试图动态地改变画笔的颜色。我写了一个非常简单的例子,但我不明白为什么它不起作用。
我在我的应用程序的DynamicResource中定义了一个前景颜色和一个使用该颜色作为ResourceDictionary的前景刷:
<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>发布于 2017-08-18 05:45:47
如果没有一个可靠地再现问题的好最小、完整和可验证的代码示例,就不可能确切地知道问题是什么。但基本问题似乎是,您试图以一种不受支持的方式使用DynamicResource。
来自文献资料
动态资源引用有一些明显的限制。至少以下一项必须为真:.所设置的属性必须是FrameworkElement或FrameworkContentElement上的属性。该属性必须由DependencyProperty支持。 ·引用是指StyleSetter中的值。 所设置的属性必须是可冻结属性上的属性,该属性作为FrameworkElement或FrameworkContentElement属性的值或Setter值提供。 因为设置的属性必须是DependencyProperty或可冻结属性,所以大多数属性更改可以传播到UI,因为属性系统确认属性更改(更改的动态资源值)。大多数控件包括逻辑,如果DependencyProperty更改,而该属性可能影响布局,则该逻辑将强制控件的另一个布局。但是,并不是所有具有DynamicResource标记扩展作为其值的属性都能以这样一种方式提供值,即它们在UI强调中实时更新。该功能可能因属性而异,也可能取决于拥有该属性的类型,甚至取决于应用程序的逻辑结构。
您在SolidColorBrush对象上设置一个属性,该对象不是FrameworkElement或FrameworkContentElement。不过,这个场景确实满足了文档中的第三个项目符号点(SolidColorBrush是一个Freezable,Freezable是作为一个FrameworkElement的值提供的)。但请注意我用粗体显示的文字。即使满足了这些要求,也不能保证它能正常工作。
有趣的是,如果您试图实现的基本方法是在直接由ResourceDictionary (例如Window)拥有的FrameworkElement上下文中实现的,那么这种方法是有效的。
为什么会这样我不知道。我的猜测是,只要您在某个FrameworkElement的上下文中,就有足够的内部状态管理来处理更新DynamicResource代理,因此它可以让它工作。
无论如何,这意味着一种可能的解决方法是将您的资源投入Window.Resources,而不是把它们放在现在的任何地方。我不知道你是否可以指望它一直都能工作;毕竟,文档中有这样的东西--所有的东西都让微软说“也许它能工作,也许它不能”。但在我看来,这种情况很可能不会在短期内被打破。
或者,您可以修改画笔资源本身。例如:
private void Button1_Click(object sender, RoutedEventArgs e)
{
Application.Current.Resources["ForegroundBrush"] = new SolidColorBrush(Colors.Green);
}这确实符合文档中更多的要求,因此似乎更有可能适用于任何未来版本的.NET (我已经验证了它今天确实有效)。
发布于 2017-08-17 16:51:09
我认为这是唯一的原因,颜色是一种值类型的数据,当您从ResourceDictionary获得一个源时,它返回颜色的值(副本),重新分配的操作不会影响原始实例(资源)。所以认为可以有很多解决办法来解决这个问题:
this.Resources["ForegroundBrush"] = new SolidColorBrush(Colors.Green);
Or
var brush = this.Resources["ForegroundBrush"] as SolidColorBrush;
if(brush != null){
brush.Color = Colors.Green;
}https://stackoverflow.com/questions/45740435
复制相似问题