zoukankan      html  css  js  c++  java
  • 用实例讲DynamicResource与StaticResource的区别 (转)

    之前我的博客文章"WPF中的资源(Resource)"中概略性地提到过DynamicResource与StaticResource的区别。其中有这么一句,确切地说是两句:静态资源在第一次编译后即确定其对象或值,之后不能对其进行修改。动态资源则是在运行时决定,当运行过程中真正需要时,才到资源目标中查找其值。

    下面用例子更详细地说明DynamicResource与StaticResource的区别。

    先看看这段XAML代码:
    // LinearGradientBrush.xaml
    <Window x:Class="BrawDraw.Com.LinearGradientBrush.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="LinearGradientBrush" Height="300" Width="300">
        <Canvas Background="{DynamicResource innerLgbResource}">
            <Canvas.Resources>
                    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1" x:Key="innerLgbResource">
                        <GradientStop Color="Yellow" Offset="0.0" />
                        <GradientStop Color="Orange" Offset="0.5" />
                        <GradientStop Color="Red" Offset="1" />
                    </LinearGradientBrush>
            </Canvas.Resources>
        </Canvas>
    </Window>
    注意:innerLgbResource是基于Yellow, Orange, Red三种颜色的渐变。

    相应的cs文件:
    // LinearGradientBrush.xaml.cs
    using System;
    using System.Windows;

    namespace BrawDraw.Com.LinearGradientBrush
    {
        /// <summary>
        /// Interaction logic for Window1.xaml
        /// </summary>
        public partial class Window1 : Window
        {
            public Window1()
            {
                InitializeComponent();
            }
        }
    }
    运行的效果:

    图1

    注意XAML代码中的这句:<Canvas Background="{DynamicResource innerLgbResource}">,Canvas的背景使用了动态资源。
    如果你将它改为<Canvas Background="{StaticResource innerLgbResource}">,将会收到错误提示:“StaticResource reference 'innerLgbResource' was not found.”
    出现此问题的原因是:StaticResource 查询行为不支持向前引用,即不能引用在引用点之后才定义的资源。
    而DynamicResource可以向前引用,即DynamicResource运行时才查找并加载所定义的资源。

    接下来我们来“变变花样”。
    先在App.xaml中加入应用程序级资源:
    <Application x:Class="BrawDraw.Com.LinearGradientBrush.App"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        StartupUri="LinearGradientBrush.xaml">
        <Application.Resources>
            <LinearGradientBrush StartPoint="0,0" EndPoint="0,1" x:Key="appLgbResource">
                <GradientStop Color="Beige" Offset="0.0" />
                <GradientStop Color="Red" Offset="0.3" />
                <GradientStop Color="Yellow" Offset="0.5" />
                <GradientStop Color="Green" Offset="0.75" />
                <GradientStop Color="Orange" Offset="1" />
            </LinearGradientBrush>
            <Style TargetType="Canvas">
                <Setter Property="Background" Value="{StaticResource appLgbResource}">
                </Setter>
            </Style>
        </Application.Resources>
    </Application>
    注意<Application.Resources>...</Application.Resources>之间的部分。这里使用了从Beige, Red, Yellow, Green到Orange五种颜色的渐变。同时,将Canvas的背景属性使用Style/Setter的方式设置为这五种给定的渐变色。由于此五种颜色是一次性设置,之后不再改变,所以使用了StaticResource。

    [讨论]
    可以使用DynamicResource吗?
    比如:<Setter Property="Background" Value="{DynamicResource appLgbResource}">
    答案是:可以!

    然后将LinearGradientBrush.xaml中<Canvas Background="{DynamicResource innerLgbResource}">这句改成:
    <Canvas Background="{StaticResource appLgbResource}">,运行结果:

    图2

    接着试验:
    (1)将<Canvas Background="{StaticResource appLgbResource}">改成:<Canvas Background="{DynamicResource appLgbResource}">试试,效果与图2一样!
    (2)将<Canvas Background="{...}">中Background属性去掉,改成:<Canvas>,运行效果也与图2一致。
    (3)如果改成:<Canvas Background="{DynamicResource innerLgbResource}">时,则显示图1所示基于基于Yellow, Orange, Red三种颜色的渐变效果。
    (4)你甚至可以这样:
    在App.xml中使用<Setter Property="Background" Value="{DynamicResource appLgbResource}">,而在LinearGradientBrush.xaml中使用<Canvas Background="{StaticResource appLgbResource}">(运行效果如图2)。

    探讨:
    1、当引用资源时,选择StaticResource还是DynamicResource的考虑因素:
    (1)在哪里创建资源?(资源的范围或层级)
    a. 资源是在一个Page/Canvas/Window中?
    b. 在应用程序范围中?
    c. 在松散的Xaml中?
    d. 在某个特定的Object(比如某个特定的Button)中?
    物件级:此时,资源只能套用在这个Object物件,或套用至该物件的子物件。
    文件级:如果将资源定义在Window或Page层级的XAML档中,那么可以套用到这个文件中的所有物件。
    应用程序级:如果我们将资源定义在App.xaml 中,那么,就可以将资源套用到应用程序内的任何地方。
    字典级:当我们把资源封装成一个资源字典, 定义到一个ResourceDictionary的XAML文件时,就可以在另一个应用程序中重复使用。

    (2) 应用程序的功能:是否在运行时改变资源?
    如果需要改变,则使用DynamicResource。
    (3) 每个资源引用类型不同的寻找行为。(需要支持向前引用吗?)

    StaticResources的适用场合:
    (1)在资源第一次引用之后无需再修改资源的值。
    (2)资源引用不会基于运行时的行为进行重新计算,比如在重新加载Page/Window的时候。
    (3)当需要设置的属性不是DependencyObject或Freezable类型的时候,用StaticResource。
    (4)当需要将资源编译到dll中,并打包为程序的一部份,或者希望在各应用程序之间共享时,也使用StaticResource。
    (5)当需要为一个自定义控件创建一个Theme,并Theme中使用资源,就需要使用StaticResource。因为StaticResource的资源查找行为时可预测的,并且本身包含在Theme中。而对于DynamicResource,即使资源是定义在Theme中,也只能等到运行时确定,导致一些可能意料不到的情况发生。
    (6)当需要使用资源设置大量的依赖属性(Dependency Property)的时候。
    由于依赖属性具有属性系统提供的值缓存机制,所以,如果能在程序装载时设置依赖属性的值,这样,依赖属性就不需要检查自己的值并返回最后的有效值了。
     
    Dynamic Resource一般使用在如下场合:
    (1)资源的值依赖一些条件,而该条件直到运行时才能确定。
    包括系统资源,或是用户可设置的资源。比如:可以创建引用系统属性诸如SystemColors,SystemFonts来设置值,而这些属性是动态的,它们的值又来自于运行环境和操作系统。
    (2)为自定义控件引用或创建Theme Style。
    (3)希望在程序运行期间调整资源字典的内容时。
    (4)希望资源可以向前引用时(如上面在Canvas中引用innerLgbResource一样)
    (5)资源文件很大,希望在运行时才加载。
    (6)要创建的Style的值可能来自于其它值,而这些值又依赖于Theme或用户的设置。
    (7)当引用资源的元素的父元素有可能在运行期改变,这个时候也需要使用动态资源。因为父元素的改变将导致资源查询的范围。
    Dynamic resource的限制条件:属性必须是依赖属性,或是Freezable的。

    资源的查询方式
    Static Resource的查询
    (1)查找使用该资源的元素的Resource字典;
    (2)顺着逻辑树向上查找父元素的资源字典,直到根节点;
    (3)查找Application资源;
    (4)不支持向前引用,即:不能引用在引用点之后才定义的资源。

    Dynamic Resource的查询
    (1)查找使用该资源的元素的Resource字典;
    如果元素定义了一个Style 属性,将查找Style中的资源字典;如果元素定义了一个Template属性,将查找FrameworkTemplate中的资源字典。
    (2)顺逻辑树向上查找父元素的资源字典,直到根节点;
    (3)查找Application资源;
    (4)查找当前激活状态下的Theme资源字典;
    (5)查找系统资源。

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/johnsuna/archive/2008/06/01/2500723.aspx

  • 相关阅读:
    打开安装 好的Microsoft Dynamics CRM 4.0 报错误为 Caller does not have enough privilege to set CallerOriginToken to the specified value 的解决办法
    基于 Windows Server 2008 的计算机对 Microsoft Dynamics CRM 4.0 的支持
    Microsoft Dynamics CRM 4.0 如何添加自定义按钮
    Microsoft Dynamics CRM 4.0 Plugin 取值,赋值,查询
    C# 中的 enum(枚举) 类型使用例子
    vue事件的绑定
    表单验证2
    node中模块
    node模块的引入
    node中的读文件
  • 原文地址:https://www.cnblogs.com/373419157/p/1621163.html
Copyright © 2011-2022 走看看