WPF应用程序资源


资源:

Microsoft Windows 应用程序通常依赖包含不可执行数据的文件,如可扩展应用程序标记语言 (XAML)、图像、视频和音频资源是可以替换应用程序的不同位置重用的对象。 WPF 支持资源具有不同的类型。 这些资源是资源的主要两种类型:XAML 资源和资源数据文件。 XAML 资源的示例包括画笔和样式。 资源数据文件是应用程序所需的不可执行的数据文件。


XAML资源:

 XAML 资源的示例包括画笔和样式。首先我们看一下在XAML中如何使用资源
在下面的代码中,定义了一个SolidColorBrush 作为页面根元素的一个资源,另外定义了不同的样式,也作为资源引用:
<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属性,你可以在任意元素上定义资源,通常在根元素上定义。 定义资源之后,可以通过使用指定键名的资源标记扩展语法来引用该资源以用于属性值,那么在程序执行的过程中是如何查找资源的呢:
当XAML 加载程序处理Button的 Background的时候
 Background="{StaticResource MyBrush}"
资源查找逻辑首先找资源字典中Button元素,没有资源键MyBrush的定义,接下来就会检查Button的父元素。在Page中定义的资源呢,Page 的逻辑树中的所有元素都可以访问该资源。该XAML加载效果图:

静态资源查找行为:
  1. 查找过程在由设置属性的元素定义的资源字典中查找所请求的键。

  2. 然后,查找过程向上遍历逻辑树,直到到达父元素及其资源字典为止。 该行为在到达根元素之前将一直持续。

  3. 接下来,检查应用程序资源。 应用程序资源是 Application 对象为您的 WPF 应用程序定义的资源字典中的资源。

资源字典中的静态资源引用必须引用在引用资源之前已在词法上定义的资源。 静态资源引用无法解析前向引用。 因此,如果您使用静态资源引用,必须设计资源字典结构,以便将逐个使用的资源定义在各相应资源字典的开头或附近。


当我们在其整个逻辑树上定义了2个相同名字的资源的时候,资源查找逻辑会一层一层往上找,找到最近的为止。
<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的。运行结果: ,可以看到会覆盖到Page中定义的。

静态资源与动态资源

资源可以作为静态资源或动态资源进行引用。我们可以看到刚才在资源标记扩展语法来引用该资源的时候,是使用的关键字StaticResource。还可以使用DynamicResource,他们之间有什么区别呢:

StaticResource标记扩展:
通过查找对已定义资源的引用,为任何 XAML 属性特性提供值。 对该资源的查找行为类似于加载时查找,它会查找以前从当前 XAML 页的标记中加载的资源以及其他应用程序源,并且将该资源值生成为运行时对象中的属性值。
使用方式:
<object property="{StaticResource key}" .../>
DynamicResource标记扩展:
为任何 XAML 属性特性提供值,该值将推迟为对已定义的资源的引用。 该资源的查找行为与运行时查找类似。
使用方式:
<object property="{DynamicResource key}" .../>

所请求的资源的键。 如果资源是在标记中创建的,则这个键最初是由 x:Key 指令分配的;如果资源是在代码中创建的,则这个键是在调用 ResourceDictionary.Add 时作为 key 参数提供的。



动态资源最适合以下集中情况:
  • 资源的值取决于直到运行时才知道的情况。 这包括系统资源,或用户可设置的资源。 例如,您可以创建引用由SystemColorsSystemFonts 或 SystemParameters 公开的系统属性的 setter 值。 这些值是真正动态的,因为它们最终来自于用户和操作系统的运行时环境。 您还可以使用可以更改的应用程序级别的主题,在此情况下,页级别的资源访问还必须捕获更改。

  • 您正在为自定义控件创建或引用主题样式。

  • 您希望在应用程序生存期调整 ResourceDictionary 的内容。

  • 您有一个存在依存关系的复杂资源结构,在这种情况下,可能需要前向引用。 静态资源引用不支持前向引用,但动态资源引用支持,因为资源直到运行时才需要进行求值,因此,前向引用不是一个相关概念。

  • 从编译或工作集角度来说,您引用的资源特别大,并且加载页时可能无法立即使用该资源。 静态资源引用始终在加载页时从 XAML 加载;而动态资源引用直到实际使用时才会加载。

  • 您要创建的样式的 setter 值可能来自受主题或其他用户设置影响的其他值。

  • 您正在将资源应用到元素,而在应用程序生存期中可能会在逻辑树中重新设置该元素的父级。 更改此父级还可能会更改资源查找范围,因此,如果您希望基于新范围对重新设置了父级的元素的资源进行重新求值,请始终使用动态资源引用。

动态资源查找行为:

  1. 查找过程在由设置属性的元素定义的资源字典中查找所请求的键。

  2. 然后,查找过程向上遍历逻辑树,直到到达父元素及其资源字典为止。 该行为在到达根元素之前将一直持续。

  3. 接下来,检查应用程序资源。 应用程序资源是 Application 对象为您的 WPF 应用程序定义的资源字典中的资源。

  4. 对于当前活动的主题,检查主题资源字典。 如果主题在运行时更改,将对值重新求值。

  5. 检查系统资源。


DynamicResource 将在初始编译过程中创建一个临时表达式,因而会将资源查找延迟到实际需要所请求的资源值来构造对象时才执行。 这可能是在加载 XAML 页之后。 将基于键搜索在所有活动的资源字典中查找资源值(从当前页范围开始),并且资源值将取代编译期间的占位符表达式。

 StaticResource 标记扩展 通过在所有可用的资源字典中查找键的值来处理该键。 这发生在加载过程中,即加载过程需要分配采用静态资源引用的属性值时。 DynamicResource 标记扩展 则通过创建一个表达式来处理键。该表达式直到实际运行应用程序时才进行求值并提供值。



区别:使用StaticResource标记扩展 是在加载的时候查找资源,而使用DynamicResource标记扩展,是在编译过程中创建一个临时表达式,在加载XAML页之后寻找资源。可以向后扩展。就是可以使用当前没有定义,而在后续定义的资源。


使用应用程序资源

应用程序定义文件定义资源部分(Resources 属性的值)。 构成应用程序的所有其他页可以访问在应用程序级别定义的资源。 这种情况下,资源是声明样式。

代码:在app.xml中:
<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>
运行结果:




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值