WPF Resource资源

WPF不但支持程序级的传统资源,同时还推出了独具特色的对象级资源,每个界面元素都可以携带自己的资源并可被自己的子级元素共享。比如后面的章节我们会讲到模板、程序样式和主题就经常放在对象资源里面。这样一来,在WPF程序中数据就分为4个等级存储了:数据库里的数据相当于存放在仓库里面,资源文件里的数据就相当于放进了旅行箱里,WPF对象资源里面的数据相当于存放在携带的背包里,变量里面的数据相当于拿在手里。

1. WPF对象资源的定义和查找

每个WPF界面元素都有一个名为Resource的属性,这个属性继承至FrameworkElement类,其类型为ResourceDictionary。ResourceDictionary能够以键值对的形式存储资源,当要使用到某个资源的时候,使用键值对的形式获取资源对象。在保存资源时,ResourceDictionary视资源对象为Object类型,所以再使用资源时先要对资源对象进行类型转换,XAML编译器能够根据Attribute自动识别资源类型,如果类型不对就会抛出异常,但在C#中检索到资源对象之后,类型转换的事情就只能由我们自己来做了。ResourceDictionary可以存储任意类型的对象。在XAML代码中向Resource添加资源时需要把正确的命名空间引入到XAML代码中,让我们来看一个例子:

<Window x:Class="WpfApplication10.wnd101"
        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="120" Width="525">
    <Window.Resources>
        <ResourceDictionary>
            <sys:String x:Key="_str">字符串</sys:String>
            <sys:Double x:Key="_db">89.7898</sys:Double>
        </ResourceDictionary>
    </Window.Resources>
    <StackPanel>
        <!--C#中可以使用FindResource查找对象资源-->
        <TextBlock x:Name="_txtBlock" FontSize="16" Text="{StaticResource ResourceKey=_str}" Height="28"/>
    </StackPanel>
</Window>

首先我们将System命名空间引入XAML代码中并映射为sys名称空间,然后在Windows.Resource里面添加了两个资源条目,一个是string类型,一个是double类型。最后我们用textBlock来消费这个资源。程序运行效果如下图:

查找资源时,先查找控件自己的Resource属性,如果没有这个资源程序会沿着逻辑树向上一级进行查找,如果连最顶端容器都没有这个资源,程序就会查找Application.Resource(也就是程序的顶级资源)。如果还没有找到,那么就只能抛出异常了。

这就好比每个界面元素都有自己的一个背包,里面可能装有各种各样的资源,使用的时候打开找一找,如果没有找到还可以去翻看上一层控件的背包,直至找到这个资源或报告没有这个资源为止。

你可能会想,如果把资源像CSS或者JS一样放在独立的文件夹里,使用时成套引用、重用时便于分发岂不更好?WPF的资源当然可以做到这一点;ResourceDictionary具有一个名为Source的属性,只要把包含资源定义的文件路径赋值给这个属性就一切搞定了!例如把皮肤以资源的形式放在XAML文件中,使用时仅需要将相应的XAML文件添加进项目并使用Source属性进行引用,你的程序就立刻变的光鲜照人。

    <Window.Resources>
        <!--用于一键换肤-->
        <ResourceDictionary Source="ShinyRed.xaml"></ResourceDictionary>
    </Window.Resources>

2. 且“动”且“静”用资源

当资源被存储进资源词典之后,我们可以使用两种方式来使用这些资源-----静态方式和动态方式。静态资源使用StackResource指的是程序载入内存时对资源的一次性使用,之后就不在去访问这个资源了;动态资源(DynamicResource)使用指的是在程序运行过程中仍然会去访问资源。显然如果你确定某些资源在程序初始化的时候只使用一次、之后不会再改变,就应该使用StaticResource,而程序运行过程中还有可能改变资源应该以DynamicResource形式使用。拿程序的主题来举例,如果程序的皮肤在运行过程中始终不变,以Static形式来使用资源就可以了。如果在程序运行过程中允许用户更改皮肤或者配色方案则必须使用DynamicResource来使用资源。

请看下面这个例子,我在Windows资源字典里放置了两个TextBlock类型资源,并分别以StaticResource和DynamicResource方式使用之:

<Window x:Class="WpfApplication10.wnd102"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="wnd102" Height="120" Width="300">
    <Window.Resources>
        <ResourceDictionary>
            <TextBlock x:Key="_txt1" Text="海上生明月"></TextBlock>
            <TextBlock x:Key="_txt2" Text="海上生明月"></TextBlock>
        </ResourceDictionary>
    </Window.Resources>
    <StackPanel>
        <Button x:Name="_btn1" Content="{StaticResource _txt1}" Height="28" ></Button>
        <!--动态资源运行时,才能更新-->
        <Button x:Name="_btn2" Content="{DynamicResource _txt2}" Height="28" ></Button>
        <Button x:Name="_btn3" Content="Update" Height="28" Click="_btn3_Click" ></Button>
    </StackPanel>
</Window>

按钮负责在程序运行过程中对资源词典里面的两个资源进行改变:

private void _btn3_Click(object sender, RoutedEventArgs e)
{
    this.Resources["_txt1"] = new TextBlock { Text = "更新成功" };
    this.Resources["_txt2"] = new TextBlock { Text = "更新成功" };
}

3. 向程序集中添加二进制资源

常见的应用程序资源有图标、图片、文本、音频、视频等,各种编程语言的编译器或者资源编译器都有能力把这些文件编译进目标文件(最终的.exe文件或者.dll文件)。资源文件在目标文件里以二进制数据形式存在、形成目标文件的资源段(Resource Section),使用时数据会被提取出来。

为了不把资源词典里的资源和应用程序里面内嵌的资源搞混,我们明确称呼资源词典里面的资源为“WPF资源”或“对象资源”,称呼应用程序内嵌资源为“程序集资源”或者“二进制资源”。特别提醒一点,WPF中写在<Application.Resource>...</Application.Resource>标签内的资源仍然是WPF资源而非二进制资源。

下面让我们看看如何向WPF程序中添加二进制资源并使用它们。

Resources.resx文件内容的组织形式也是“键-值”对,编译后,Resources.resx会形成Properties名称空间中的Resource类,使用这个类的方法或属性就能获取资源。为了让XAML编译器能够访问这个类,一定要把Resources.resx的访问级别由Internal改为public。利用资源文件编辑器,可以资源文件的字符串里添加两个条目,然后分别在XAML代码和C#代码中访问他们。

在XAML代码中使用Resources.resx中的资源,需要把程序的Properties名称映射为XAML名称空间,然后使用x:Static标签扩展来访问资源。

<Window x:Class="WpfApplication10.wnd103"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prop="clr-namespace:WpfApplication10.Properties"
        FontSize="16"
        Title="wnd103" Height="130" Width="340">
    <StackPanel>
        <!--C#中可以使用Properties.Resources.访问-->
        <TextBlock x:Name="_txtBlock1" Text="{x:Static prop:Resources.password}"></TextBlock>
        <TextBlock x:Name="_txtBlock2" Text="{x:Static prop:Resources.userName}"></TextBlock>
    </StackPanel>
</Window>

有一点特别提醒大家,如果想让外部文件编译进二进制资源,必须在属性窗口把文件的Build Action属性值设为Resource。并不是每种文件都会自动设置为Resource,比如图片文件会,MP3文件就不会,一般情况下,如果Build Action的值设为Resource,则Copy to Output Directory属性设置为Do Not Copy;如果不希望以资源的形式使用外部文件,可以把Build
Action属性设置为None,而把Copy to Output Directory设置为Copy Always。另外,Build Action属性的下拉列表里面有一个颇具迷惑性的值Embeded Resource,不要选择这个值。

4. 使用PACK URI路径访问二进制资源

WPF对二进制资源的访问有自己的一套方法,称为PACK URI路径。有时候死记硬背能够让读者快速学习又能帮助作者偷点懒。比如,WPF的PACK URI路径,你只需要记住这个格式就可以了:

pack://application,,,[/程序集名称;][可选版本号;][文件夹名称/][文件名称]  

而实际上pack://applicationi,,,可以省略、程序集名称和版本号常使用省略值,所以剩下的就只有这个了:

[文件夹名称/][文件名称]  

我们看看例子:

<Window x:Class="WpfApplication10.wnd104"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="wnd104" Height="200" Width="300">
    <Grid>
        <Image x:Name="_image" Source="Resources/Images/Aodi.jpg" Stretch="Fill"></Image>
    </Grid>
</Window>

也可使用C#访问:

_image.Source = new BitmapImage(new Uri(@"Resources/Images/Aodi.jpg", UriKind.Relative));

参考:《深入浅出WPF》

时间: 2024-10-13 19:58:35

WPF Resource资源的相关文章

WPF 之 资源(Resource)

1.什么叫WPF的资源(Resource)? 资源是保存在可执行文件中的一种不可执行数据.在WPF的资源中,几乎可以包含图像.字符串等所有的任意CLR对象,只要对象有一个默认的构造函数和独立的属性. 也就是说,应用程序中非程序代码的内容,比如点阵图.颜色.字型.动画/影片档以及字符串常量值,可将它们从程序中独立出来,单独包装成"资源(Resource)". 包含两种资源:静态资源(Static Resource),动态资源(Dynamic Resources).这两者的区别是: [1]

WPF 中资源路径的问题

WPF 中资源路径的问题 1. 引用当前工程的资源(注意xxxx.png的build action 应设置为Resource 或Embedded Resource) ? 1 <ImageBrush ImageSource="/currentAssemblyName;component/subfoldername/xxxx.png"/> 2.引用其它工程的资源  (注意xxxx.png的build action 应设置为Resource 或Embedded Resource)

Android插件化(三)加载插件apk中的Resource资源

Android加载插件apk中的Resource资源 简介 如何加载未安装apk中的资源文件呢?我们从android.content.res.AssetManager.java的源码中发现,它有一个私有方法addAssetPath,只需要将apk的路径作为参数传入,我们就可以获得对应的AssetsManager对象,然后我们就可以使用AssetsManager对象,创建一个Resources对象,然后就可以从Resource对象中访问apk中的资源了.总结如下: 1.新建一个AssetManag

wpf 引用资源文件

一.什么是资源 通常使用  WPF  资源作为重用通常定义的对象和值的简单方法. 在 WPF 中资源通常用作"样式"(Style).样式模板.数据模板等. 二.资源的定义及 XAML 中引用 资源可以定义在以下几个位置: 1 应用程序级资源 定义在 App.xaml 文件中, 作为整个应用程序共享的资源存在  ; 在 App.xaml 文件中定义: <Application.Resources> <ResourceDictionary> <Resource

22个经典的WPF源代码资源合集

22个经典的WPF源代码资源合集 http://download.csdn.net/album/detail/1503

WPF 调用资源图片

原文:WPF 调用资源图片 最近做的wpf项目中,在开发的时候,把图片放到了bin下面,采用了imagePath =System.IO.Directory.GetCurrentDirectory()+"/images/starShow.jpg";获得图片是可以的,可是发布之后却获取不到图片,这让我很纠结,后来通过把图片添加到了资源中,然后调用资源即可解决了问题 imagePath = "pack://application:,,,/Financial;component/Pr

WPF之资源

我们把有用的东西称为资源,程序中存放数据的地方有很多,可以放在数据库里,可以存储在变量里,界于数据库存储与变量存储之间,我们还可以把数据存储在程序主体之外的文件里.外部文件与程序主体分离,这就有可能丢失或损坏,为了避免丢失或损坏,编译器允许我们把外部文件编译进程序主体,称为程序主体不可分割的一部分,这就是传统意义上的程序资源,也成为二进制资源. WPF不但支持程序级的传统资源,同时还推出了独具特色的对象级资源.每个界面元素都可以携带自己的资源并可被自己的子级元素共享. 对象资源 每个WPF的界面

[WPF]静态资源(StaticResource)和动态资源(DynamicResource)

一.文章概述 本演示介绍了WPF的静态资源和动态资源的基本使用,并对两者做了简单的比较. 静态资源(StaticResource)指的是在程序载入内存时对资源的一次性使用,之后就不再访问这个资源了:动态资源(DynamicResource)使用指的是在程序运行过程中然会去访问资源. 相关下载(代码.屏幕录像):http://pan.baidu.com/s/1c0q2BVM 在线播放:http://v.youku.com/v_show/id_XODE4MTI1MzYw.html 温馨提示:如果屏幕

【转】【WPF】资源读取 URI

一开始看到WPF里面经常用如下语句来构造资源文件Uri: Uri uri = new Uri("/AssemblyName;component/image.png"); 我还以为这种格式的字符串是URI标准规定的,但是网上查了一下却没发现有这种格式的URI字符串. URI是统一资源标识符,通用文法为: 协议名(http,https,ftp,file等)+冒号+协议所对应的内容 URI又分为URL和URN,URL是用来定义一个资源的访问路径.而URN则是用来定义一个资源的名称.(http