如果希望在多個項目之間共享資源,可建立資源字典。資源字典隻是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項目中包含的資源。

下一步是為存儲在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/
本文版權歸作者和部落格園共有,歡迎轉載,但必須給出原文連結,并保留此段聲明,否則保留追究法律責任的權利。