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

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

或作为动态资源

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

大多数时候(总是?),只有一个有效,另一个会在运行时抛出异常。但我想知道为什么:

  • 主要区别是什么。比如内存或性能影响
  • WPF 中是否有“画笔始终是静态的”和“模板始终是动态的”等规则?

认为 静态与动态之间的选择并不像看起来那么随意......但我看不到其中的规律。

有帮助吗?

解决方案

A 静态资源 将在应用程序实际运行之前加载 XAML 期间解析并分配给该属性。它只会被分配一次,并且对资源字典的任何更改都会被忽略。

A 动态资源 在加载期间将 Expression 对象分配给属性,但直到运行时要求 Expression 对象提供值时才实际查找资源。这会推迟查找资源,直到运行时需要为止。一个很好的例子是对稍后在 XAML 中定义的资源的前向引用。另一个例子是直到运行时才存在的资源。如果源资源字典发生更改,它将更新目标。

其他提示

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

<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 中声明
  • 这也是在它们被使用之前。

希望我消除了一些困惑。

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

逻辑资源允许您在 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的颜色属性更改为Orange和Pink,那么只有当资源用作DynamicResource时,它才会反映在元素上。下面是代码中更改资源的代码:

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

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

来源:
WPF:静态资源对比动态资源

  1. 静态资源使用 第一的 价值。动态资源使用 最后的 价值。
  2. DynamicResource 可用于嵌套样式,而 StaticResource 则不能。

假设您有这个嵌套的 Style 字典。浅绿色位于根级别,而粉色嵌套在网格内。

<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 在渲染网格时会将浅绿色按钮覆盖为粉色。

StaticResource静态资源

DynamicResource动态资源

请记住,VS 设计器将 DynamicResource 视为 StaticResource。它将获得第一个值。在这种情况下,VS Designer 会将按钮呈现为浅绿色,尽管它实际上最终呈现为粉色。

当根级样式 (LightGreen) 被删除时,StaticResource 将引发错误。

主要区别是什么。比如内存或性能影响

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

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

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

WPF 中是否有“画笔始终是静态的”和“模板始终是动态的”等规则?

最佳实践是使用静态资源,除非有特定原因,例如您想要动态更改后面代码中的资源。您希望使用动态资源的另一个实例包括当您使用 SystemBrushes、SystenFonts 和系统参数时。

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

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

正如其他人提到的,静态资源将在编译时查找。用户控件不能引用托管/父控件中定义的资源。不过,在这种情况下可以使用 DynamicResource。

动态资源的重要好处

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

但是,除非您的资源非常大并且 复杂。

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

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

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

动态资源:

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