WPF 资源(StaticResource 静态资源、DynamicResource 动态资源)

一)基础知识

静态资源(Static Resource),动态资源(Dynamic Resources)。这两者的区别是:静态资源在第一次编译后即确定其对象或值,之后不能对其进行修改。动态资源则是在运行时决定,当运行过程中真正需要时,才到资源目标中查找其值。因此,我们可以动态地修改它。由于动态资源的运行时才能确定其值,因此效率比静态资源要低。

动态修改,是两种资源最显著的差异,也是极其重要的知识点,下面这个例子就是最好的说明,简单但能解决问题。

<Window x:Class="StaticDynamicResources.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib" 
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>     
        <sys:String x:Key="Content" >
           Hello World!
        </sys:String>
    </Window.Resources>
    <Grid>
        <WrapPanel>
            <TextBlock Text="静态"/>
            <TextBox Text="{StaticResource Content}" Width="100" x:Name="TextBox1"/>
            <TextBlock Text="动态" Margin="10,0,0,0"/>
            <TextBox Text="{DynamicResource Content}" Width="100" x:Name="TextBox2"/>
            <Button Content="改变资源值" Click="ChangeBtn_Click" Width="100"/>       
        </WrapPanel>
    </Grid>
</Window>
private void ChangeBtn_Click(object sender, RoutedEventArgs e)
  {
      this.Resources["Content"] = "内容变了";
  } 

我们点击Button发现,后面的TextBox值可以发生变化,因为它用是的动态资源。有趣的是,将上述程序Window.Resources放在获取资源后面,会出现错误将会收到错误提示:“StaticResource reference 'content' was not found.”

出现此问题的原因是:StaticResource 查询行为不支持向后引用,即不能引用在引用点之后才定义的资源。而DynamicResource可以向后引用,即DynamicResource运行时才查找并加载所定义的资源。

(二) 运用场合

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)希望资源可以向前引用时(如上面在WrapPanel中引用content一样)
(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)查找系统资源。

非共享资源

正常情况下资源使用的是统一对象实例,这种行为成为共享,如果希望每次都创建一个新的对象可如下设置。x:Shared="False"

<ImageBrush x:Key="TitleBrush"  x:Shared="False"  TileMode="Tile" ViewboxUnits="Absolute" Viewport="0 0 32 32"
                    ImageSource="happyface.jpg" Opacity="0.3"></ImageBrush>

通过代码访问资源

private void txt_TextChanged(object sender, RoutedEventArgs e)
        {
            Button cmd = (Button)sender;
            ImageBrush brush = (ImageBrush)cmd.FindResource("TitleBrush");
        }

可使用TryFindResource()代替FindResource()。如果找不到资源会返回null,而不是抛异常。

 应用程序资源

窗口不是查找应用程序资源的最后一站,如果在控件或其他容器中知道包含窗口或页面找不到指定的资源。WPF会继续查找为应用程序定义的资源。在Visual Studio中,这些资源在App.xaml文件的标记中定义的资源

<Application x:Class="HelloWpf.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="GridDemoWindow.xaml">
    <Application.Resources>
        <ImageBrush x:Key="TitleBrush" TileMode="Tile" ViewboxUnits="Absolute" Viewport="0 0 32 32"
                    ImageSource="happyface.jpg" Opacity="0.3"></ImageBrush>
    </Application.Resources>
</Application>

应用程序资源为整个应用程序中重用对象提供了一种极佳的方法。

系统资源

当某个元素查找资源时,应用程序资源仍然不是最后一站。如果没有在应用程序资源中找到所需的资源,元素还会继续查找系统资源。

系统资源的三个类

  • SystemColors   访问系统颜色设置。
  • SystemFonts    访问字体设置。
  • SystemParamerers  封装了大量的设置列表,这些设置描述了各种屏幕像素的标准尺寸、键盘和鼠标设置、屏幕尺寸以及各种图形效果(如热跟踪、阴影以及拖动窗口时显示窗口内容)是否已经打开。

StaticResource指向的对象通常是Xaml里定义的Style或者Template之类。
x:static指向的对象通常是后台代码里的某个静态类。用来在Xaml中引用类的静态字段或静态属性,如Text={x:Static local:Window1.ShowText}。 

静态更改:

<Button Background="{x:Static SystemColors.DesktopBrush}" Content="Hello, World!" />

动态更改:

<Button Background="{DynamicResource {x:Static SystemColors.DesktopBrushKey}}" Content="Hello, World!" />

资源字典

如果希望多个项目中共享资源,可创建资源字典。资源字典只是xaml文档,除了存储希望使用的资源外,不做其他任何事情。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ImageBrush x:Key="TitleBrush" TileMode="Tile" ViewboxUnits="Absolute" Viewport="0 0 32 32"
                    ImageSource="happyface.jpg" Opacity="0.3"></ImageBrush>
</ResourceDictionary>

使用资源字典将其整合到应用程序资源中,可添加多个 

<Application x:Class="HelloWpf.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="GridDemoWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="AppBrushs.xaml"></ResourceDictionary>
                <ResourceDictionary Source="AppBrushs2.xaml"></ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>  
    </Application.Resources>
</Application>

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: WPF静态资源是不能进行双向绑定的。静态资源是在应用程序启动时由XAML解析器解析和创建的,并且之后不能进行修改。这意味着一旦静态资源被创建,就无法通过双向绑定来更新源属性。 双向绑定是一种机制,可以保持源属性和目标属性之间的同步。但是,静态资源在运行时是只读的,不允许修改。因此,即使源属性的值发生改变,静态资源也无法自动更新。 如果需要在WPF中实现双向绑定,可以使用动态资源或数据绑定的方式来实现。动态资源是可以在运行时修改的资源,可以通过改变源属性的值来实现更新。数据绑定是一种更为灵活的机制,可以将源属性与目标属性绑定在一起,并在值发生变化时实时更新。 总之,WPF静态资源不能进行双向绑定,但可以使用动态资源或数据绑定来实现相似的效果。 ### 回答2: WPF静态资源不能直接双向绑定。静态资源是在应用程序运行期间创建的,并且通常用于提供应用程序中多个元素共享的资源,如颜色、字体、样式等。它们被视为只读资源,无法随着绑定目标的更改而自动更新。 但是,在某些情况下,可以通过将静态资源与绑定目标的属性绑定到一个对象,并在该对象上实现双向绑定来实现类似的效果。这个对象可以是一个中间的绑定器或视图模型,它可以在用户交互或其他事件中更新静态资源的值,并将这些更改传递给绑定的元素。 使用这种方法,可以实现在静态资源和绑定目标之间的双向同步。但需要注意的是,这种方法需要手动管理同步过程,并且可能需要更复杂的代码来实现。 总体而言,虽然WPF静态资源本身并不支持双向绑定,但可以通过巧妙地使用中间对象来实现类似的效果,使静态资源在某种程度上实现双向绑定。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值