天天看點

【WPF學習】第三十五章 資源字典

  如果希望在多個項目之間共享資源,可建立資源字典。資源字典隻是XAML文檔,除了存儲希望使用的資源外,不做其他任何事情。

一、建立資源字典

  下面是一個資源字典示例,它包含一個資源:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ImageBrush x:Key="TileBrush" TileMode="Tile"
                    ViewportUnits="Absolute" Viewport="0 0 32 32"
                ImageSource="happyface.jpg" Opacity="0.3"></ImageBrush>
</ResourceDictionary>      

  當為應用程式添加資源字典時,務必将Build Action設定為Page(與其他任意XAML檔案一樣)。這樣可保證為了獲得最佳性能而将資源字典編譯為BAML。不過,将資源字典的Build Action設定為Resource也是非常完美的,這樣它會被嵌入到程式集中,但不會被編譯。當然,在運作時解析它的速度要稍慢一些。

二、使用資源字典

  為了使用資源字典,需要将其合并到應用程式某些位置的資源集合中。例如,可在特定視窗中執行此操作,但通常将其合并到應用程式的資源集合中。如下所示:

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

  上面的标記通過明确建立ResourceDictionary對象進行工作。資源集合總是ResourceDictionary對象,但這隻是需要明确指向細節進而可以設定ResourceDictionary.MergedDictionaries屬性的一種情況。如果不執行這一步驟,MergedDictionaries屬性将為空。

  MergedDictionaries是ResourceDictionary對象的一個集合,可使用該集合提供自己希望使用的資源的集合。這個示例中有兩個資源集合:一個在AppBrusheds.xaml資源字典中定義,另一個在WizardBrushes.xaml中定義。

  如果希望添加自己的資源并合并到資源字典中,隻需要在MergedDictionaries部分之前或之後放置資源就可以了,如下所示:

<Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="AppBrushes.xaml"/>
                <ResourceDictionary Source="WizardBrushes.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            <ImageBrush x:Key="GraphicalBrush1"></ImageBrush>
            <ImageBrush x:Key="GraphicalBrush2"></ImageBrush>
        </ResourceDictionary>
    </Application.Resources>      

  使用資源字典的一個原因是為了定義一個或多個可重用的應用程式“皮膚",可将”皮膚“應用到控件上。另一個原因是為了存儲需要被本地化的内容。

三、在程式集之間共享資源

  如果希望在多個應用程式之間共享資源字典,可複制并分發包含資源字典的XAML檔案。這是最簡單的方法,但這樣不能對版本進行任何控制。更有條理的方法是将資源字典編譯到單獨的類庫程式集中,并分發元件。

  當共享包含一個或多個資源字典的編譯過的程式集時,還需要面對另一個挑戰——需要有一種方法提取所希望的資源并在應用程式中使用資源。為此,可使用兩種方法。最直覺的解決方法是使用代碼建立合适的ResourceDictionary對象。例如,如果類庫程式集中有名為ReusableDictionary.xaml的資源字典,那麼可使用下面的代碼手動建立該資源字典:

ResourceDictionary resourceDictionary=new ResourceDictionary();
resourceDictionary.Source=new Uri("ResourceLibrary;component/ReusableDictionary.xaml",UriKind.Relative);      

  上面的代碼片段使用了在本章前面介紹的pack URI文法。它構造了一個相對URI,該URI指向另一個程式集中名為ReusableDictionary.xaml的編譯過的XAML資源。一旦建立ResourceDictionary對象,就可以從集合中手動檢索所需的資源了:

cmd.Background=(Brush)resourceDictionary["TileBrush"];      

  然而,不必手動指定資源。當加載新的資源字典時,視窗中的所有DynamicResource引用都會被自動重新評估。

  如果不想編寫任何代碼,還有另一種選擇。可使用ComponentResourceKey标記擴充,該标記擴充是專門針對這種情況而設計的。使用ComponentResourceKey為資源建立鍵名。通過執行這一步驟,告知WPF準備在程式集之間共享資源。

  在繼續執行任何操作前,需要確定已經為資源字典提供了正确的名稱。為了讓這種技巧生效,必須将資源字典放置到generic.xaml檔案中,并且必須将該檔案放到應用程式檔案夾的Themes子檔案夾中。generic.xaml檔案中的資源被認為是預設主題的一部分,并且它們總是可用的。

  下圖顯示了合理的檔案組織方式,頂部的項目名為ResourceLibray,generic.xaml檔案被放在正确的檔案夾中。底部的項目名為Resources。該項目有指向ResourceLibrary項目的引用,是以該項目可使用ResourceLibray項目中包含的資源。

【WPF學習】第三十五章 資源字典

  下一步是為存儲在ResourceLibray程式集中希望共享的資源建立名。當使用ComponentResourceKey時,需要提供兩部分資訊:類庫程式集中類的引用和描述性的資源ID。類引用是WPF允許的其他程式集共享資源的關鍵部分。當使用資源時,需要提供相同的類引用和資源ID。

  該類的實際外觀并不重要,它不需要包含代碼。定義該類型的程式集就是ComponentResourceKey将要從中查找資源的程式集。

  下面是generic.xaml檔案的完整标記,它包含了一個單獨資源——一個使用不同圖形的ImageBrush對象:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ResourceLibrary"
    >

 
    <ImageBrush
      x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:CustomResources}, ResourceId=SadTileBrush}"
      TileMode="Tile"
      ViewportUnits="Absolute" Viewport="0 0 32 32"
      ImageSource="ResourceLibrary;component/sadface.jpg" Opacity="0.3">
    </ImageBrush>

</ResourceDictionary>      

  如果眼光敏銳的話,将在該例中發現一個意外細節。ImageSource屬性不在被設定為圖像名(sadface.jpg),而是使用更複雜的相對URI,明确地訓示圖像時ResourceLibray元件的一部分。這是必須的步驟,因為将在其他應用程式中使用該資源。如果隻是使用圖像名,應用程式就會在它自己的資源中查找圖像。真正需要的是指定存儲圖像的元件的相對URI。

  現在已經建立了資源字典,可在另一個應用程式中使用它了。首先,確定已經為類庫程式集定義了字首,如下所示:

<Window x:Class="Resources.ResourceFromLibrary"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:res="clr-namespace:ResourceLibrary;assembly=ResourceLibrary"
    Title="ResourceFromLibrary" Height="300" Width="300"    
    >      

  然後可使用包含ComponentResourceKey的DynamicResource(這是合理的,因為ComponentResourceKey是資源名)。在使用資源字典的應用程式中使用ComponentResourceKey,就是在類庫中使用的ComponentResourceKey。在此,提供了對同一個類的引用和相同的資源ID。唯一的差別是可能使用不同的XAML名稱空間字首。該例使用res字首而不是local字首。進而強調CustomResources類是在另一個程式集中定義的這樣一個事實:

<Button Background="{DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type res:CustomResources}, ResourceId=SadTileBrush}}"
            Padding="5" Margin="5"
            FontWeight="Bold" FontSize="14">
            A Resource From ResourceLibrary</Button>      

  現在該例完成了。但還可以采用一個附加步驟,使資源更容易使用。可定義一個靜态屬性,讓它傳回需要使用的正确ComponentResourceKey。通常在元件的類中定義該屬性,如下所示:

public class CustomResources
    {
        public static ComponentResourceKey SadTileBrush
        {
            get
            {
                return new ComponentResourceKey(
                    typeof(CustomResources), "SadTileBrush");
            }
        }
    }      

  現在可使用Static标記擴充通路該屬性并應用資源,而不必在标記中使用很長的ComponentResourceKey:

<Button Background="{DynamicResource {x:Static res:CustomResources.SadTileBrush}}"
        Padding="5" Margin="5"
        FontWeight="Bold" FontSize="14">
      A Resource From ResourceLibrary
    </Button>      

  在本質上,這種便捷方法與前面介紹的SystemXxx類使用相同的技術。例如,當檢索SystemColors.WindowTextBrushKey時,所接受的也是正确的資源鍵對象。唯一的差別是,它是私有SystemResourceKey(而不是ComponentResourceKey)的一個執行個體。這兩個類都繼承自ResourceKey抽象類。

作者:Peter Luo

出處:https://www.cnblogs.com/Peter-Luo/

本文版權歸作者和部落格園共有,歡迎轉載,但必須給出原文連結,并保留此段聲明,否則保留追究法律責任的權利。

繼續閱讀