zoukankan      html  css  js  c++  java
  • WPF之神奇的资源

    WPF中的资源有两种,一种称为"程序集资源"(assembly resource),另一种称为"对象资源"(object resource)也称为"逻辑资源",WPF中统称后者为"逻辑资源"。

    一、程序集资源
    应用程序中的XAML、图片、音频、视频等文件,都可以将其作为程序集资源组织起来。
    程序集资源可以以以下3种方式打包:
    1.资源文件(Resource File):直接嵌入到程序集中。
    2.内容文件(Content File):该文件的相关信息会编译到程序集中,如文件的相对位置。
    3.Site of Origin文件:不参加编译,应用程序不知道该文件是否存在。

    资源文件
    向项目中添加一个jpg的图片,默认的Build Action就为Resource,在Xaml中的2种使用方式如下:

            <Image Source="1.jpg" />
            <Image  Source="pack://application:,,,/1.jpg"/>

     答疑:
    属性中的Build Action中有一个Embedded Resource和Resource,区别呢?
    两者都可以将文件编译到程序集资源中去,前者用于Winform项目中嵌入程序集资源,在WPF中则选择后者。

    内容文件
    右键文件设置Build Action属性为Content,同时设置属性Copy to Output Directory 设置为Copy always或者Copy if newer,则可以复制到bin\debug下。

         <Image Source="Images/1.jpg"></Image>
         <Image Source="/Images/2.jpg" Grid.Row="1"></Image>

    以上两个方式均可以显示输出为Content的图片。

    Site of Origin文件
    Site of Orign文件根本不参加编译,应用程序编译时候不知道该文件是否存在,只有运行时候才知道。
    配置此类文件,右键属性设置Build Actoin为None,Copy to Output Directory设置为Copy always或者Copy if newer。通过代码访问需要使用GetRemoteStream方法。

            Uri uri = new Uri("/siteoforiginfile.xaml", UriKind.Relative);
                StreamResourceInfo info = Application.GetRemoteStream(uri);
                System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
                Page page = (Page)reader.LoadAsync(info.Stream);
                this.siteoforiginfileframe.Content = page;

    Uri语法
    Uri可以通过当前程序集、被引用的程序集、相对程序集的一个位置和任意位置标识访问资源。
    WPF中的Uri由3部分组成,第一个部分的协议是pack;第2个部分成为"authority",有两种值:一是application://,表示编译时知道的文件,主要指资源和内容文件;二是siteoforign://,表示Site of Origin文件;第3部分是路径,如果是引用程序集中资源,情况会稍微复杂一点。路径必须包含引用的程序集名称和一个Component标识,表示引用的不是本地程序集的资源,有时还需要加上版本信息。
    WPF中的路径分为相对和绝对路径。WPF中的默认Uri设置是pack://application:,,,,因此引用site of orign文件必须要使用绝对路径。

    pack://application:,,,/ResourceFile.xaml
    /ResouceFile.xaml

    第一种为绝对路径,第二种为相对路径。

     <DockPanel>
        <StackPanel DockPanel.Dock="Top">
    
          <GroupBox Header="Absolute Pack URIs">
            <StackPanel>
              <Frame Source="pack://application:,,,/ResourceFile.xaml" />
              <Frame Source="pack://application:,,,/Subfolder/ResourceFile.xaml" />
              <Frame Source="pack://application:,,,/ReferencedAssembly;component/ResourceFile.xaml" />
              <Frame Source="pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml" />
              <Frame Source="pack://application:,,,/ReferencedAssembly;v1.0.0.1;component/ResourceFile.xaml" />
              <Frame Source="pack://application:,,,/ContentFile.xaml" />
              <Frame Source="pack://application:,,,/Subfolder/ContentFile.xaml" />
              <Frame Source="pack://siteoforigin:,,,/SiteOfOriginFile.xaml" />
              <Frame Source="pack://siteoforigin:,,,/Subfolder/SiteOfOriginFile.xaml" />
            </StackPanel>
          </GroupBox>
    
          <GroupBox Header="Relative Pack URIs">
            <StackPanel>
              <Frame Source="/ResourceFile.xaml" />
              <Frame Source="/Subfolder/ResourceFile.xaml" />
              <Frame Source="/ReferencedAssembly;component/ResourceFile.xaml" />
              <Frame Source="/ReferencedAssembly;component/Subfolder/ResourceFile.xaml" />
              <Frame Source="/ReferencedAssembly;v1.0.0.1;component/ResourceFile.xaml" />
              <Frame Source="/ContentFile.xaml" />
              <Frame Source="/Subfolder/ContentFile.xaml" />
              <Frame Source="pack://siteoforigin:,,,/SiteOfOriginFile.xaml" />
              <Frame Source="pack://siteoforigin:,,,/Subfolder/SiteOfOriginFile.xaml" />
            </StackPanel>
          </GroupBox>
    
        </StackPanel>
    
        <GroupBox Header="Version-Specified Pack URIs">
          <DockPanel>
            <Button DockPanel.Dock="Top" Click="click0">Get Resource File in Reference Assembly v1.0.0.0</Button>
            <Button DockPanel.Dock="Top" Click="click1">Get Resource File in Reference Assembly v1.0.0.1</Button>
            <Frame Name="frame" NavigationUIVisibility="Hidden" />
          </DockPanel>
        </GroupBox>
    
      </DockPanel>
       void click0(object sender, RoutedEventArgs e) {
                Uri uri = new Uri("/VersionedReferencedAssembly;v1.0.0.0;component/ResourceFile.xaml", UriKind.RelativeOrAbsolute);
                this.frame.Source = uri;
            }
    
            void click1(object sender, RoutedEventArgs e)
            {
                Uri uri = new Uri("/VersionedReferencedAssembly;v1.0.0.1;component/ResourceFile.xaml", UriKind.RelativeOrAbsolute);
                this.frame.Source = uri;
            }

    此示例为微软提供的Uri的用法,几乎涵盖了所有的使用方法,源码下载如下:
    WPFUriSample


    WPF中的URI处理顺序
    WPF中有两个处理系统,即siteoforigin:///和applicatoin:///,前者按照提供的路径查找SiteofOrigin文件,后者的比较复杂:
    1。先查找路径是否为内容文件
    2.如果未找到,则继续在程序集的资源中查找;如果找到则为资源问及那;
    3.如果未找到,则为无效。

    逻辑资源(对象资源)
    看如下例子:

        <Window.Resources>
            <ImageBrush x:Key="TileBrush" x:Shared ="True"  TileMode="Tile"
                    ViewportUnits="Absolute" Viewport="0 0 32 32"
                    ImageSource="happyface.jpg" Opacity="0.3" ></ImageBrush>
        </Window.Resources>
      <Button Background="{StaticResource TileBrush}" Padding="5"
                  FontWeight="Bold" FontSize="14" Margin="5" Click="Button_Click">A Tiled Button 静态资源引用</Button>

    以上例子在Resource中定义了一个画刷资源,在Button中使用其设置背景颜色,通过"{StaticResouce ReourceKey}"语法进行资源的引用。

    不仅仅画刷(或者是应用于样式)可以作为资源,普通的.Net对象也可用于资源,如下:

    xmlns:s ="clr-namespace:System;assembly=mscorlib"

    在Windows标签中引用System命名空间,使用如下:

        <Window.Resources>
            <s:String x:Key="ButtonContent">
                逻辑资源Demo
            </s:String>
        </Window.Resources>

    调用资源,作为文本显示

    <Button Grid.Row="2" Margin="5" Content="{StaticResource ButtonContent}" Click="Button_Click_1" />


    静态资源和动态资源

     WPF提供了两种访问逻辑资源的方式,一是静态资源,通过StaticResource标记扩展来实现,前面引用资源的方式均为此方式;二是动态资源,通过DynamicResource标记扩展
    来实现。
    静态资源和动态的资源主要区别在于,静态资源只从资源字典中查找一次资源,后者在应用程序需要时查找资源.

    <Button Background="{StaticResource TileBrush}" Padding="5"
    FontWeight="Bold" FontSize="14" Margin="5" Click="Button_Click">A Tiled Button 静态资源引用</Button>
    <Button Grid.Row="1" Background="{DynamicResource TileBrush}" Padding="5"
    FontWeight="Bold" FontSize="14" Margin="5" Click="Button_Click">A Tiled Button 动态资源引用</Button>
    
            <Button Grid.Row="3"  Margin="5"Click="Button_Click" />

    例子中的两个按钮一个是静态资源方式引用,一种是动态资源方式引用,在Click中修改资源如下:

                ImageBrush brush = (ImageBrush)this.Resources["TileBrush"];
                ImageBrush newbrush = brush.Clone();
                newbrush.Viewport = new Rect(0, 0, 5, 5);
                this.Resources["TileBrush"] = newbrush;

    点击按钮会神奇的发现,动态资源方式的按钮的背景会变化哦.
    注意:切忌,最后一句代码,必须要重新给旧的资源对象赋值.

    共享资源
    默认情况下,当有一个资源被应用到多处时使用的都是一个对象实例,这是极好的了.如果希望应用程序在使用资源的每处都有一个不同的对象实例,可以在资源中标记
    x:Shared="False".
    例如将Image作为资源,由于其派生自Visual类,会被添加到逻辑树和可视化树中,因此不能将Image的对象作为资源多次使用,否则会抛出异常哦.但是可以将Image资源
    标记成x:Shared="False",这样在应用这个资源时实际创建了不同的对象实例。

    使用ResourceDictionary组织管理资源
    WPF中提供了ResourceDictionary(资源字典)类型的XAML文件组织资源,右键项目ADD菜单-->Resource Dictionary即可创建一个资源字典,资源可以分类别
    放在同一个资源文件。如下降画刷资源放在Brushes.xaml文件中:

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local ="clr-namespace:mumu_resourcesLib">
        <ImageBrush
          x:Key="SadFaceBrush"
          TileMode="Tile"
          ViewportUnits="Absolute" Viewport="0 0 32 32"
          ImageSource="sadface.jpg" Opacity="0.3">
        </ImageBrush>
    </ResourceDictionary>

    在App.xaml文件中通过MergedDictionaries包含资源字典文件,这样应用程序就可以访问Brushes.xaml文件中的资源了:

    <Application x:Class="mumu_shareresources.App"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        StartupUri="Window1.xaml">
        <Application.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="Brushes.xaml"/>
                </ResourceDictionary.MergedDictionaries>    
            </ResourceDictionary>
        </Application.Resources>
    </Application>

    使用如下:

     <Button Background="{StaticResource SadFaceBrush}" />



    程序集之间共享资源:
    有如下目录结构的程序

     ResourceDemo项目为WPF Application,ResourceLibrary为WPF Libiary。在ResourceLibrary中有Brushes.xaml资源文件,代码如下:

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <ImageBrush
          x:Key="SadFaceBrush"
          TileMode="Tile"
          ViewportUnits="Absolute" Viewport="200 200 200 200"
          ImageSource="1.jpg">
        </ImageBrush>
    </ResourceDictionary>

    在APP.xaml中引用资源文件:

    <Application x:Class="WpfApplication9.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 StartupUri="MainWindow.xaml">
        <Application.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary  Source="/ResourceLibrary;component/Brushes.xaml"></ResourceDictionary>
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </Application.Resources>
    </Application>

    程序集之间引用使用"/程序集;component/资源文件"这样的语法来进行调用。
    使用方法还是这样:

     <Button Background="{StaticResource SadFaceBrush}"></Button>


    好了,WPF的资源介绍暂且到这里,欢迎大家讨论分享.



  • 相关阅读:
    Mockito一个方法的实例
    LIst与ArrayList区别
    mockito入门学习
    eclipse中调整字体大小和改变背景颜色
    常用sql语句
    eclipse导入代码和重新编译
    windows下登录linux的常用工具SecureCRT和常用命令
    junit4
    接口测试
    java环境
  • 原文地址:https://www.cnblogs.com/ListenFly/p/2953096.html
Copyright © 2011-2022 走看看