WPF学习之资源Resources文档格式.docx
《WPF学习之资源Resources文档格式.docx》由会员分享,可在线阅读,更多相关《WPF学习之资源Resources文档格式.docx(12页珍藏版)》请在冰豆网上搜索。
Imagesinformation16.png"
Imagespass16.png"
Imagespass32.png"
Imagesunknown16.png"
Imageswarning.gif"
Imageswarning16.png"
EmbeddedResourceInclude="
LoginForm.resx"
>
<
SubType>
Designer<
/SubType>
DependentUpon>
LoginForm.cs<
/DependentUpon>
/EmbeddedResource>
OptionsForm.resx"
OptionsForm.cs<
PageHistory.resx"
PageHistory.cs<
上图所示是一个普通的WinForm应用程序的项目文件,对于添加到其内部的二进制资源文件其默认的构建动作便是Content-表明其作为一个松散文件存储,只要保证其对应路径的文件存在则可以自动加载(而无需再你的打包文件中必须包含)。
而你也会看到EmbeddedResource构建动作,这是WinForm的构建动作,它和Resource构建动作很相似,会在程序集中嵌入一个二进制资源,但是WPF中因为嵌入式资源比WPF还要优先,所以需要尽量避免使用。
之所以推荐使用Resource和Content构建类型是因为这样嵌入的资源可以很容易的在XAML中被引用,而且对于WPF的统一资源识别符也是专门针对这两种构建动作而设计的。
相反地,对于EmbeddedResource构建动作嵌入的资源是不能在XAML中被引用的,除非自定义代码。
访问二进制资源
访问二进制资源最普通的就是对松散文件的访问,这和普通的.NET应用程序没什么两样,直接看例子吧:
<
StackPanelOrientation="
Horizontal"
HorizontalAlignment="
Center"
ButtonBackground="
Yellow"
BorderBrush="
Red"
Margin="
5"
<
ImageHeight="
21"
Source="
zoom.gif"
/>
/Button>
defaultThumbnailSize.gif"
previous.gif"
/StackPanel>
上述的的松散文件只需要以Content构建加入项目即可.这只是普通的访问方式,当然也是我们常用的,但也有很多你可能需要用到哦,不妨看看:
资源URI
资源
zoom.gif
存放于当前程序集;
或是添加到项目的松散文件。
Folder/zoom.gif
如果内部有目录结构时加入相对目录结构。
C:
Imageszoom.gif
file:
//C:
/Images/zoom.gif
绝对路径的松散文件
FileServerImageszoom.gif
共享目录的松散文件
位于某个站点上的松散文件
AssemblyReference;
Component/ResourceName
访问嵌入到另外一个程序集或EXE文件内的资源。
Component是关键字,必须写。
例如:
MyDll;
Component/Images/zoom.gif;
pack:
//siteOfOrigin:
,,/Images/zoom.gif
访问位于部署位置的资源。
2. 逻辑资源
逻辑资源是WPF特有的资源类型,它是存储在元素的Resources属性中的.NET对象,通常需要共享给多个子元素。
换句话说,你可以声明一个SolidColorBrush对象当作一个逻辑资源,你也可以声明一个Style,然后再后续的XAML中简单通过{StaticResourceResourceName}来使用。
资源定义需要有一个在ResourceDictionary中唯一的关键字x:
Key(单独的ResourceDictionary中的键名不可以重复,多个ResourceDictionary中键名可以重复,会根据在逻辑数上的lookup的顺序来就近生效)。
例如下边的逻辑资源声明:
Windowx:
Class="
WpfApplication1.Window2"
xmlns="
xmlns:
x="
Title="
Window2"
Height="
300"
Width="
400"
Window.Resources>
SolidColorBrushx:
Key="
buttonBackground"
Yellow<
/SolidColorBrush>
borderBrush"
Red<
LinearGradientBrushx:
backgroundBrush"
StartPoint="
0,0"
EndPoint="
1,1"
<
GradientStopColor="
Blue"
Offset="
0"
/GradientStop>
White"
0.5"
1"
/LinearGradientBrush>
/Window.Resources>
Window.Background>
StaticResourceResourceKey="
/Window.Background>
Grid>
{StaticResourcebuttonBackground}"
{StaticResourceborderBrush}"
Margin="
28"
<
Imageszoom.gif"
/Image>
Imagesprevious.gif"
{DynamicResourceborderBrush}"
Imagesnext.gif"
/Grid>
/Window>
一个资源可以被以StaticResource或者DynamicResource的方式来引用,这是以标记扩展(StaticResource/DynamicResourceMarkupExtension)来标注的。
去以StaticResource还是以DynamicResource来引用一个资源,这取决于:
你是以什么样的方式来为你的应用创建资源的:
每个Page?
一个Application?
一个松散XAML文件?
还是一个只包含资源定义的程序集?
需要在运行时更新你的资源吗?
查找资源的行为—向前查询?
资源本身的行为和属性
3. StaticResource–静态资源
StaticResource仅仅会被应用一次---在第一次需要资源时加载。
而且这种引用方式不支持向前加载,所有的资源定义必须在引用之前定义。
StaticResource通常用在:
设计的APP是将所有的资源放入Page或者App这个级别的ResourceDictionary中的,而且不需要在运行时重新计算—例如只保存一些松散文件,逻辑资源的声明等。
不需要给DependencyObject或者Freezable的对象设置属性。
ResourceDictionary将被编译进DLL.
需要给很多的DependencyProperty赋值。
将一个资源以StaticResource引用,需要用到StaticResourceMarkupExtension。
它在已经定义的资源中查询特定key的value为XAML的某个属性赋值。
这个查询的行为与load-time查找类似,在当前Page的XAML中或者所有Application的Resources中查找,并在运生成运行时对象。
XAMLAttributeUsage
objectproperty=”StaticResourcekey}”…/>
XAMLObjectElementUsage
object>
object.Property>
StaticResourceResourceKey=“key”…/>
/object.Property>
/object>
前者是我们经常会用到的方式,比如给一个属性赋予一个早先定义的话刷格式:
而后者我们在前面的例子中也看到了,用法稍微特殊,其实在这个情况下这个资源肯定是一个逻辑资源,相当于一段声明对象的代码。
比如给window设背景:
StaticResource的查找行为
首先检查此对象本身的Resources集合内是否有匹配值(根据ResourceKey)
其次会在逻辑树中向上搜寻父元素的ResourceDictionary.
最后会检查Root级别的比如Page,Window,Application等。
4. DynamicResource–动态资源
与StaticResource不同的是,DynamicResource可以在程序运行时重新评估/计算资源来生成对应的对象/值,它支持向前引用,只要请求的key在整个应用程序内的任何ResourcesDictionary定义过就可以被加载。
如果有多个相同的key存在,则最后搜索到的资源为有效。
动态资源常用于以下情况:
资源直到运行时才能被取定其值的。
这些包含想系统资源,或者通过用户交互/用户可以设定的值。
例如你可以用SetterProperty语法来引用一些系统资源像SystemColors,SystemFonts等,这些是真正的DynamicResource,因为他们是来自用户的运行环境。
在Customcontrol中有创建/引用主题风格的需求.
在运行过程中调整(比如添加或者合并)ReourceDictionary.
需要向前引用的场景。
创建的Style的值与当前用户设定的主题或其他设定有关的。
运行过程中可能更改逻辑树的次序的。
下面的代码片段演示了如何在XAML中引用SystemFonts,这需要用DynamicResource标记:
Stylex:
SimpleFont"
TargetType="
{x:
TypeButton}"
SetterProperty="
FontSize"
Value="
{DynamicResource{x:
StaticSystemFonts.IconFontSizeKey}}"
FontWeight"
StaticSystemFonts.MessageFontWeightKey}}"
FontFamily"
StaticSystemFonts.CaptionFontFamilyKey}}"
/Style>
DynamicResource的查找行为
首先遍历请求对象本身定义的Resources集合。
然后遍历逻辑树上当前请求对象的父对象,直到遍历到Root(如Page.Reources,Window.Resources,UserControl.Resources等)
随后会遍历应用程序的Resources(即Application.Resources)
进而会Check当前激活的Theme的资源。
最后才会去遍历SystemResources.
在程序中你可以通过myWindow.Resources[“key”]的方式来直接访问一个资源。
另外,WPF还提供了TryFindResource(key)和FindResource(key)来支持资源搜索。
FindResource方法在没找到资源的情况下会触发ResourceReferenceKeyNotFoundException异常。
其实通过上边的示例我们可以很清楚的看到,在使用静态资源的地方我们往往都可以使用动态资源,他们并没有什么合适与否之说,而选择它们中的哪一个,完全取决于你是否需要资源的使用者发现更新。
我们可以再来比较一下二者的区别:
对于资源的更新会反映在那些使用了动态资源的元素上,这是他们最主要的区别。
性能上:
因为动态资源要跟踪变化,所以需要占用更多的资源。
而静态资源往往是在window或page加载之后来引用,动态资源会改善加载时间。
但静态资源在使用时却会有些许性能的提升。
动态资源只能设置依赖属性只,而静态资源可以在任何地方使用。
比如,我们可以声明一个逻辑资源把它当作一个元素来用,而动态资源却无法做到:
WpfApplication1.Window3"
Window3"
x:
prev"
ButtonHeight="
20"
70"
Content="
Content"
当你在XAML中使用StaticResource时,是不支持ForwardReference的,也就是说任何资源必须在XAML文件中声明之后才可以使用。
如果是在同一个元素中定义,则只能使用DynamicResource。
Background="
{DynamicResourcewinBackground}"
winBackground"
5. 资源的应用
前变也已经说过可以引用别的程序集的资源,那么到底如何引用呢?
另外,我们都是在说XAML中引用资源,那么代码中又该如何去做呢?
我们又通常会在什么地方定义资源呢?
这里就来说一下这几个问题,以及某些特殊情况下的定义。
共享资源
默认情况下,当有一个资源被引用到多个地方是,使用的都是同一个对象实例,这通常是理想的行为。
但你同样也可以把x:
Shared=”False”来让每个引用资源的地方都生成一个不同的对象实例,这样可以独立进行修改。
这通常用于多逻辑资源的声明。
程序代码中定义和应用资源
在代码中定义一个新的Resource,你需要首先得到一个ResourceDictionary的实例,然