资源:
Microsoft Windows 应用程序通常依赖包含不可执行数据的文件,如可扩展应用程序标记语言 (XAML)、图像、视频和音频。资源是可以替换应用程序的不同位置重用的对象。 WPF 支持资源具有不同的类型。 这些资源是资源的主要两种类型:XAML 资源和资源数据文件。 XAML 资源的示例包括画笔和样式。 资源数据文件是应用程序所需的不可执行的数据文件。
XAML资源:
<Window x:Class="ResourceTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="600" Width="600">
<Page Name="root"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Page.Resources>
<!--定义画笔颜色为黄绿色-->
<SolidColorBrush x:Key="MyBrush" Color="YellowGreen" />
<!--定义一个样式 作用类型为Border 名字:PageBackground 设置属性background为Black -->
<Style TargetType="Border" x:Key="PageBackground">
<Setter Property="Background" Value="Black"/>
</Style>
<Style TargetType="TextBlock" x:Key="TitleText">
<Setter Property="Background" Value="Yellow"/>
<Setter Property="DockPanel.Dock" Value="Top"/>
<Setter Property="FontSize" Value="33"/>
<Setter Property="Foreground" Value="#4E87D4"/>
<Setter Property="FontFamily" Value="Trebuchet MS"/>
<Setter Property="Margin" Value="0,40,10,10"/>
</Style>
<Style TargetType="TextBlock" x:Key="Label">
<Setter Property="DockPanel.Dock" Value="Right"/>
<Setter Property="FontSize" Value="22"/>
<Setter Property="Foreground" Value="{StaticResource MyBrush}"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Margin" Value="0,3,10,0"/>
</Style>
</Page.Resources>
<StackPanel>
<Border Style="{StaticResource PageBackground}">
<DockPanel>
<TextBlock Style="{StaticResource TitleText}">Title</TextBlock>
<TextBlock Style="{StaticResource Label}">Label</TextBlock>
<TextBlock DockPanel.Dock="Top" HorizontalAlignment="Left" FontSize="36" Foreground="{StaticResource MyBrush}" Text="Text" Margin="20" />
<Button DockPanel.Dock="Top" HorizontalAlignment="Left" Height="30" Background="{StaticResource MyBrush}" Margin="40">Button</Button>
<Ellipse DockPanel.Dock="Top" HorizontalAlignment="Left" Width="100" Height="100" Fill="{StaticResource MyBrush}" Margin="40" />
</DockPanel>
</Border>
</StackPanel>
</Page>
</Window>
每个框架级别的元素都会有一个Resource属性,你可以在任意元素上定义资源,通常在根元素上定义。
定义资源之后,可以通过使用指定键名的资源标记扩展语法来引用该资源以用于属性值,那么在程序执行的过程中是如何查找资源的呢:
Background="{StaticResource MyBrush}"
静态资源查找行为:
-
查找过程在由设置属性的元素定义的资源字典中查找所请求的键。
-
然后,查找过程向上遍历逻辑树,直到到达父元素及其资源字典为止。 该行为在到达根元素之前将一直持续。
-
接下来,检查应用程序资源。 应用程序资源是 Application 对象为您的 WPF 应用程序定义的资源字典中的资源。
资源字典中的静态资源引用必须引用在引用资源之前已在词法上定义的资源。 静态资源引用无法解析前向引用。 因此,如果您使用静态资源引用,必须设计资源字典结构,以便将逐个使用的资源定义在各相应资源字典的开头或附近。
<Window x:Class="ResourceTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="600" Width="600">
<Page Name="root"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Page.Resources>
<!--定义画笔颜色为黄绿色-->
<SolidColorBrush x:Key="MyBrush" Color="YellowGreen" />
</Page.Resources>
<StackPanel>
<StackPanel.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Red"/>
</StackPanel.Resources>
<Button DockPanel.Dock="Top"
HorizontalAlignment="Left"
Height="30"
Background="{StaticResource MyBrush}" Margin="40">Button
</Button>
</StackPanel>
</Page>
</Window>
我们在Button中使用资源键MyBrush,在其逻辑树上定义了2个MyBrush,分别在StackPanel中和Page中,结果资源查找逻辑会使用最StackPanel的。运行结果:
静态资源与动态资源
StaticResource标记扩展:
<object property="{StaticResource key}" .../>
DynamicResource标记扩展:
为任何 XAML 属性特性提供值,该值将推迟为对已定义的资源的引用。 该资源的查找行为与运行时查找类似。使用方式:<object property="{DynamicResource key}" .../>
所请求的资源的键。 如果资源是在标记中创建的,则这个键最初是由 x:Key 指令分配的;如果资源是在代码中创建的,则这个键是在调用 ResourceDictionary.Add 时作为 key 参数提供的。
-
资源的值取决于直到运行时才知道的情况。 这包括系统资源,或用户可设置的资源。 例如,您可以创建引用由SystemColors、SystemFonts 或 SystemParameters 公开的系统属性的 setter 值。 这些值是真正动态的,因为它们最终来自于用户和操作系统的运行时环境。 您还可以使用可以更改的应用程序级别的主题,在此情况下,页级别的资源访问还必须捕获更改。
-
您正在为自定义控件创建或引用主题样式。
-
您希望在应用程序生存期调整 ResourceDictionary 的内容。
-
您有一个存在依存关系的复杂资源结构,在这种情况下,可能需要前向引用。 静态资源引用不支持前向引用,但动态资源引用支持,因为资源直到运行时才需要进行求值,因此,前向引用不是一个相关概念。
-
从编译或工作集角度来说,您引用的资源特别大,并且加载页时可能无法立即使用该资源。 静态资源引用始终在加载页时从 XAML 加载;而动态资源引用直到实际使用时才会加载。
-
您要创建的样式的 setter 值可能来自受主题或其他用户设置影响的其他值。
-
您正在将资源应用到元素,而在应用程序生存期中可能会在逻辑树中重新设置该元素的父级。 更改此父级还可能会更改资源查找范围,因此,如果您希望基于新范围对重新设置了父级的元素的资源进行重新求值,请始终使用动态资源引用。
-
查找过程在由设置属性的元素定义的资源字典中查找所请求的键。
-
然后,查找过程向上遍历逻辑树,直到到达父元素及其资源字典为止。 该行为在到达根元素之前将一直持续。
-
接下来,检查应用程序资源。 应用程序资源是 Application 对象为您的 WPF 应用程序定义的资源字典中的资源。
-
对于当前活动的主题,检查主题资源字典。 如果主题在运行时更改,将对值重新求值。
-
检查系统资源。
使用应用程序资源:
<Application x:Class="ResourceTest.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml">
<Application.Resources>
<Style TargetType="Button" x:Key="GelButton" >
<Setter Property="Margin" Value="1,2,1,2"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Background" Value="YellowGreen"/>
</Style>
</Application.Resources>
</Application>
下面的示例演示了引用上例中定义的应用程序级资源的 XAML 页。在当前页中没有找到具有“GelButton”键的资源,所以请求资源的资源查找范围超出当前页,进入已定义的应用程序级资源。
<Window x:Class="ResourceTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="600" Width="600">
<Page Name="root"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<StackPanel>
<Button Height="50" Width="50"
Style="{StaticResource GelButton}"
Content="Button 1"/>
<Button Height="50" Width="50"
Style="{StaticResource GelButton}"
Content="Button 1"/>
</StackPanel>
</Page>
</Window>
运行结果: