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

Isa*_*avo 455 .net wpf resources xaml

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

<Rectangle Fill="{StaticResource MyBrush}" />
Run Code Online (Sandbox Code Playgroud)

或者作为DynamicResource

<ItemsControl ItemTemplate="{DynamicResource MyItemTemplate}"  />
Run Code Online (Sandbox Code Playgroud)

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

  • 主要区别是什么?像记忆或性能影响
  • WPF中的规则是"画笔总是静态的"和"模板总是动态的"等吗?

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

Phi*_*ght 451

一个静态资源将得到解决,并且应用程序实际运行前发生的XAML负荷期间分配给属性.它只会被分配一次,并且忽略对资源字典的任何更改.

一个DynamicResource装载过程中分配一个表达式对象的属性,但实际上并没有查找资源直到运行时表达式对象要求的值.这会延迟查找资源,直到在运行时需要它为止.一个很好的例子是对稍后在XAML中定义的资源的前向引用.另一个例子是直到运行时才会存在的资源.如果源资源字典已更改,它将更新目标.

  • 最后一句非常重要:`如果源资源字典被更改,它将更新目标 (10认同)
  • 如果要附加的资源在其使用点之前在XAML中定义,并且在运行的应用程序的生命周期内不会更改,则使用StaticResource.在这种情况下,您可以使用StaticResource获得更好的性能. (5认同)
  • 在我需要使用DynamicResource之前需要改变什么?以模板为例:我定义了一次但当然触发器和东西可以改变模板的内容,但模板仍然是相同的.StaticResource会在这里吗? (4认同)
  • 是否适用于这两种情况,如果是,那么在这种情况下会有什么不同? (4认同)
  • @IsakSavo考虑具有颜色主题的UI,使用动态资源,您可以将一个字典交换为另一个字典,并且新字典中引用资源的任何内容都将自动更新. (3认同)
  • 因此,StaticResource就像一个常量,而DynamicResource就像一个变量。 (2认同)

Aks*_*y J 115

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

<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>
Run Code Online (Sandbox Code Playgroud)

在这里,我已经使用了按钮和窗口的动态资源,并没有宣布它anywhere.Upon运行时,层次结构的资源字典将checked.Since我还没有确定呢,我想默认将被使用.

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

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

如果他们使用过StaticResource:

  • 必须在XAML中声明资源
  • 这也是"之前"使用它们.

希望我清除了一些困惑.


小智 30

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


las*_*iya 29

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

<Window.Resources>
    <RadialGradientBrush x:Key="myGradientBrush">
        <GradientStop Color="Green" Offset="0"/>
        <GradientStop Color="Blue" Offset="2"/>
    </RadialGradientBrush>
</Window.Resources>
Run Code Online (Sandbox Code Playgroud)

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

<Grid Background="{StaticResource myGradientBrush}"></Grid>
Run Code Online (Sandbox Code Playgroud)

要么:

<Grid Background="{DynamicResource myGradientBrush}"></Grid>
Run Code Online (Sandbox Code Playgroud)

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

换句话说,如果RadialGradientBrush的color属性在代码中更改为Orange和Pink,那么只有在将资源用作DynamicResource时才会反映元素.下面是代码中更改资源的代码:

RadialGradientBrush radialGradientBrush =
    new RadialGradientBrush(Colors.Orange, Colors.Pink);
this.Resources["myGradientBrush"] = radialGradientBrush;
Run Code Online (Sandbox Code Playgroud)

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

来源:
WPF:StaticResource与DynamicResource

  • 源代码中的解释非常好,但是复制粘贴特别是没有被原始回答者引用(它被@ Em1的编辑添加)是不好的.所以,答案很好,但它甚至不能被投票 (4认同)

Jes*_*aya 19

  1. StaticResource使用第一个值.DynamicResource使用最后一个值.
  2. DynamicResource可用于嵌套样式,StaticResource则不能.

假设您有这个嵌套的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>
Run Code Online (Sandbox Code Playgroud)

在视图中:

<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>
Run Code Online (Sandbox Code Playgroud)

StaticResource将按钮呈现为LightGreen,它是样式中找到的第一个值.DynamicResource将LightGreen按钮覆盖为粉红色,因为它呈现网格.

静态资源 静态资源

DynamicResource DynamicResource

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

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


Cha*_*thJ 13

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

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

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

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

WPF中的规则是"画笔总是静态的"和"模板总是动态的"等吗?

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


Man*_*ani 7

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

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

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


zam*_*dar 5

动态资源的重要好处

\n\n

如果应用程序启动时间过长,则必须使用动态资源,\n因为静态资源始终在创建窗口或应用程序时加载,而动态资源\n在首次使用\xe2\x80\x99时加载。

\n\n

但是,\xe2\x80\x99 不会看到任何好处,除非你的资源非常庞大且复杂。

\n


小智 5

仅当设置的属性位于从依赖对象派生或可冻结的对象上时,才能使用动态资源,而静态资源可以在任何地方使用。您可以使用静态资源抽象出整个控制。

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

  1. 当运行时不需要反应资源变化时。
  2. 如果您需要大量资源的良好性能。
  3. 在引用同一词典中的资源时。

动态资源:

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