WPF中的StaticResource和DynamicResource有什么区别?

时间:2008-10-14 11:54:58

标签: .net wpf xaml resources

在WPF中使用画笔,模板和样式等资源时,可以将它们指定为StaticResources

<Rectangle Fill="{StaticResource MyBrush}" />

或作为DynamicResource

<ItemsControl ItemTemplate="{DynamicResource MyItemTemplate}"  />

大多数时候(总是?),只有一个工作,另一个会在运行时抛出异常。但我想知道原因:

  • 主要区别是什么?像记忆或性能影响
  • WPF中是否有规则,例如“画笔总是静态的”和“模板总是动态的”等等。

假设静态与动态之间的选择并不像看起来那样随意......但我看不到模式。

9 个答案:

答案 0 :(得分:432)

在加载实际运行应用程序之前发生的XAML期间,将解析StaticResource并将其分配给属性。它将仅被分配一次,并且忽略对资源字典的任何更改。

DynamicResource在加载期间为该属性分配一个Expression对象,但在运行时要求Expression对象输入值时,实际上不会查找资源。这会延迟查找资源,直到在运行时需要它为止。一个很好的例子是对稍后在XAML中定义的资源的前向引用。另一个例子是直到运行时才会存在的资源。如果源资源字典已更改,它将更新目标。

答案 1 :(得分:113)

我也对他们感到困惑。请参阅以下示例:

<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。由于我没有定义它,我想我将使用默认值。

如果我添加下面的代码来点击Button的事件,因为他们使用DynamicResource,后台将相应更新。

private void ButtonNew_Click(object sender, RoutedEventArgs e)
{
    this.Resources.Add(  "PinkBrush"
                         ,new SolidColorBrush(SystemColors.DesktopColor)
                       );
}

如果他们使用过StaticResource:

  • 资源必须在XAML中声明
  • 那也是“之前”使用它们。
希望我清除了一些困惑。

答案 2 :(得分:30)

StaticResource将在对象构造上解析 每次控件需要资源时,都会评估和解析DynamicResource。

答案 3 :(得分:27)

逻辑资源允许您在XAML中定义对象,这些对象不是可视树的一部分,但可以在您的用户界面中使用。逻辑资源的一个示例是Brush,它用于提供颜色方案。通常,这些对象被定义为资源,由应用程序的多个元素使用。

<Window.Resources>
    <RadialGradientBrush x:Key="myGradientBrush">
        <GradientStop Color="Green" Offset="0"/>
        <GradientStop Color="Blue" Offset="2"/>
    </RadialGradientBrush>
</Window.Resources>

现在,上面声明的资源可以用作静态或动态资源。需要记住的一点是,在使用静态资源时,应首先在XAML代码中定义它,然后才能引用它。静态和动态资源可用作:

<Grid Background="{StaticResource myGradientBrush}"></Grid>

或:

<Grid Background="{DynamicResource myGradientBrush}"></Grid>

StaticResource和DynamicResource之间的区别在于引用元素如何检索资源。 StaticResource仅由引用元素检索一次,并用于资源的整个生命周期。另一方面,每次使用引用的对象时都会获取DynamicResource。

更简单地说,如果RadialGradientBrush的color属性在代码中更改为Orange和Pink,那么只有当资源用作DynamicResource时,它才会反映元素。下面是代码中更改资源的代码:

RadialGradientBrush radialGradientBrush =
    new RadialGradientBrush(Colors.Orange, Colors.Pink);
this.Resources["myGradientBrush"] = radialGradientBrush;

DynamicResource的缺点是它降低了应用程序性能,因为每次使用时都会检索资源。最好的做法是使用StaticResource,直到有特定原因使用DynamicResource。

来源:
WPF: StaticResource vs. DynamicResource

答案 4 :(得分:19)

  1. StaticResource使用第一个值。 DynamicResource使用最后值。
  2. DynamicResource可用于嵌套样式,StaticResource则不能。
  3. 假设您有这个嵌套的Style字典。 LightGreen位于根级别,而Pink嵌套在网格内。

    <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 StaticResource的

    DynamicResource DynamicResource

    请记住,VS Designer将DynamicResource视为StaticResource。它将获得第一个价值。在这种情况下,VS Designer会将按钮渲染为LightGreen,尽管它实际上最终为Pink。

    当删除根级别样式(LightGreen)时,StaticResource将抛出错误。

答案 5 :(得分:13)

主要区别是什么?像记忆或性能影响

当底层对象发生变化时,会出现静态和动态资源之间的差异。如果在Resources集合中定义的Brush在代码中被访问并设置为不同的对象实例,则Rectangle将不会检测到此更改。

静态资源通过引用元素检索一次,并用于资源的生命周期。而DynamicResources每次使用时都会检索。

动态资源的缺点是它们往往会降低应用程序性能。

WPF中是否有规则,例如“画笔总是静态的”和“模板总是动态的”等等?

最佳做法是使用静态资源,除非您有特殊原因想要动态更改代码中的资源。您希望使用动态资源的实例的另一个示例包括使用SystemBrushes,SystenFonts和System Parameters时。

答案 6 :(得分:7)

发现所有答案都很有用,只想添加一个用例。

在复合WPF场景中,您的用户控件可以通过将该资源称为DynamicResource来利用任何其他父窗口/控件(即将承载此用户控件)中定义的资源。

正如其他人所说,Staticresource将在编译时查找。用户控件不能引用托管/父控件中定义的那些资源。虽然,在这种情况下可以使用DynamicResource。

答案 7 :(得分:3)

动态资源的重要好处

如果应用程序启动需要很长时间,则必须使用动态资源, 因为静态资源总是在创建窗口或应用程序时加载,而动态资源 在他们第一次使用时加载。

但是,除非您的资源非常庞大,否则您将看不到任何好处 复杂。

答案 8 :(得分:1)

动态资源只能在设置属性的对象上使用,该对象派生自依赖对象或freezable,其中静态资源可以在任何地方使用。 您可以使用静态资源抽象出整个控件。

在以下情况下使用静态资源:

  1. 不需要在运行时更改反应资源。
  2. 如果您需要有大量资源的良好表现。
  3. 引用同一词典中的资源。
  4. 动态资源:

    1. 在运行时之前,不知道属性或样式设置器主题的值
      • 这包括系统,应用程序,基于主题的设置
      • 这也包括前向参考。
    2. 引用页面,窗口,用户控件加载时可能无法加载的大型资源。
    3. 在自定义控件中引用主题样式。