当在WPF中使用画笔、模板和样式等资源时,它们可以指定为StaticResources
<Rectangle Fill="{StaticResource MyBrush}" />
或者作为一个动态资源
<ItemsControl ItemTemplate="{DynamicResource MyItemTemplate}" />
大多数时候(总是?),只有一个工作,而另一个将在运行时抛出异常。但我想知道为什么:
主要的区别是什么?比如对内存和性能的影响
WPF中是否存在“笔刷总是静态的”和“模板总是动态的”之类的规则?
我认为静态和动态之间的选择并不像看起来那么随意……但我看不出规律。
StaticResource使用第一个值。DynamicResource使用last值。
DynamicResource可以用于嵌套样式,StaticResource不能。
假设您有这个嵌套样式字典。LightGreen位于根级别,而Pink嵌套在Grid中。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type Grid}">
<Style.Resources>
<Style TargetType="{x:Type Button}" x:Key="ConflictButton">
<Setter Property="Background" Value="Pink"/>
</Style>
</Style.Resources>
</Style>
<Style TargetType="{x:Type Button}" x:Key="ConflictButton">
<Setter Property="Background" Value="LightGreen"/>
</Style>
</ResourceDictionary>
在视图:
<Window x:Class="WpfStyleDemo.ConflictingStyleWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ConflictingStyleWindow" Height="100" Width="100">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles/ConflictingStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Button Style="{DynamicResource ConflictButton}" Content="Test"/>
</Grid>
</Window>
StaticResource将按钮渲染为LightGreen,这是它在样式中找到的第一个值。DynamicResource将覆盖LightGreen按钮为粉红色,因为它呈现网格。
StaticResource
DynamicResource
请记住VS Designer将DynamicResource视为StaticResource。它会得到第一个值。在这种情况下,VS Designer将按钮渲染为浅绿色,尽管它实际上最终是粉红色。
当删除根级样式(LightGreen)时,StaticResource将抛出一个错误。
StaticResource使用第一个值。DynamicResource使用last值。
DynamicResource可以用于嵌套样式,StaticResource不能。
假设您有这个嵌套样式字典。LightGreen位于根级别,而Pink嵌套在Grid中。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type Grid}">
<Style.Resources>
<Style TargetType="{x:Type Button}" x:Key="ConflictButton">
<Setter Property="Background" Value="Pink"/>
</Style>
</Style.Resources>
</Style>
<Style TargetType="{x:Type Button}" x:Key="ConflictButton">
<Setter Property="Background" Value="LightGreen"/>
</Style>
</ResourceDictionary>
在视图:
<Window x:Class="WpfStyleDemo.ConflictingStyleWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ConflictingStyleWindow" Height="100" Width="100">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles/ConflictingStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Button Style="{DynamicResource ConflictButton}" Content="Test"/>
</Grid>
</Window>
StaticResource将按钮渲染为LightGreen,这是它在样式中找到的第一个值。DynamicResource将覆盖LightGreen按钮为粉红色,因为它呈现网格。
StaticResource
DynamicResource
请记住VS Designer将DynamicResource视为StaticResource。它会得到第一个值。在这种情况下,VS Designer将按钮渲染为浅绿色,尽管它实际上最终是粉红色。
当删除根级样式(LightGreen)时,StaticResource将抛出一个错误。
我也对他们感到困惑。请看下面的例子:
<Window x:Class="WpfApplicationWPF.CommandsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CommandsWindow" Height="300" Width="300">
<StackPanel>
<Button Name="ButtonNew"
Click="ButtonNew_Click"
Background="{DynamicResource PinkBrush}">NEW</Button>
<Image Name="ImageNew"
Source="pack://application:,,,/images/winter.jpg"></Image>
</StackPanel>
<Window.Background>
<DynamicResource ResourceKey="PinkBrush"></DynamicResource>
</Window.Background>
</Window>
这里我已经使用动态资源按钮和窗口,并没有在任何地方声明它。在运行时,将检查层次结构的ResourceDictionary。因为我没有定义它,所以我猜将使用默认值。
如果我添加下面的代码来click event of Button,因为他们使用的是DynamicResource,所以后台会相应更新。
private void ButtonNew_Click(object sender, RoutedEventArgs e)
{
this.Resources.Add( "PinkBrush"
,new SolidColorBrush(SystemColors.DesktopColor)
);
}
如果他们使用了StaticResource:
资源必须在XAML中声明
这也是“before”他们被使用。
希望我澄清了你们的疑惑。
主要的区别是什么?比如对内存和性能的影响
当底层对象发生变化时,静态资源和动态资源之间的区别就显现出来了。如果在Resources集合中定义的Brush在代码中被访问并设置为不同的对象实例,Rectangle将不会检测到此更改。
静态资源通过引用元素检索一次,并在资源的生命周期内使用。而DynamicResources则在每次使用时进行检索。
动态资源的缺点是它们往往会降低应用程序的性能。
WPF中是否存在“笔刷总是静态的”和“模板总是动态的”之类的规则?
最好的做法是使用静态资源,除非有特定的原因,比如你想在后面的代码中动态地改变资源。当你使用systembrush, systemfonts和System Parameters时,你会想要使用动态资源的另一个例子。