1. 程式人生 > >資源字典——程式集之間的資源共享

資源字典——程式集之間的資源共享

最近在做一個WPF的應用,我想在WPF的應用中使用資源字典應該是很常見的事情,由於是初次設計這種程式,對WPF也不是很熟悉,不免會遇上一些問題,當然很多也是一些基礎的低階的,比如本文將要介紹的“資源字典將如何在不同程式集之間進行共享”的問題就是一個很基礎的技術點。在我的應用程式的設計中將資源字典作為程式集單獨設計為類庫還不是很必要,但我想我們常見的系統中這麼做應該是很不錯的選擇吧,所以,我就很想明白此時我應該怎麼做,可是在我從網上查詢相關資料時發現這方面的介紹不是很多,而且,介紹的也不夠清楚,大多還是很籠統,給的例子也都千篇一律——以我的智商還不能做到被一點即通。於是便查閱了一些書籍,終於在《WPF程式設計寶典——C# 2010版》中找的較詳細的介紹,所以,我想把我學到的做個總結記錄下來以供大家參考和我以後的檢視。

  我想我這裡即將介紹的這個知識對於初始WPF的人應該還是能有幫助的吧,希望如此。至少,我看了書裡的介紹還是覺得還是很清楚的,如果我這裡的介紹給到家帶來困擾了,還希望能夠不客氣的指出,另外,也可以去看下書中原文(原文寫的還是很清楚,條理也很清晰的)。關於資源字典、如何建立和使用資源字典是很簡單的,隨便查一下資料就能明白了,這裡我們還是先關注一下它在不同程式集間的共享。

  如果只是在不同窗體或控制元件之間共享倒是簡單了,關鍵是怎麼能在不同程式集間共享。尤其是大點的專案,我們很有可能需要單獨建立一個資源字典的程式集作為資源類庫進行共享。那如果是這種情況我們該怎麼辦呢?除了直接拷貝資源字典的XAML檔案並分發以外(當然這不是什麼好的選擇)我們還有兩個辦法:1、使用程式碼建立合適的 ResourceDictionary 物件(這種做法比較直觀);2、使用 ComponentResourceKey 標記擴充套件,該標記擴充套件也是專門為此設計的。

  一、使用程式碼建立 ResourceDictionary 物件:

    1、假設資源字典專用類庫為 ResourceDictionaryLibrary ,要使用其中的一個資源字典為 ButtonBackgroundDic.xaml 的資源字典,可以使用下面的程式碼進行訪問:

ResourceDictionary resDictionary = new ResourceDictionary();
resDictionary.Source = new Uri("ResourceDictionaryLibrary;component/ButtonBackgroundDic.xaml",UriKind.Relative);

     2、在使用時,我們就可以通過Key來手動檢索所需的資源了,如下程式碼所示(其中 BtnBackgound_SkyBlue 是我要用的資源的 Key ;btn 是我使用該資源的一個 Button ):

this.btn.Background = (Brush)resourceDic["BtnBackgound_SkyBlue"];

     注:

      在上面程式碼中使用了 pack URI 語法,這裡僅作簡單介紹,具體語法講解請查閱相關資料:

      語法格式為 ResourceName(相對URI)或 pack://application:,,,/ResourceName(絕對URI),兩種寫法是等效的;但對於檢索嵌入到其他資源庫中的資源時語法格式為 AssemblyName;component/ResourceName(相對URI)或 pack://application:,,,/AssemblyName;component/ResourceName(絕對URI)(如在上述例子中使用的格式為:”AssemblyName;component/ResourceName“)。

   二、使用 ComponentResourceKey 標記擴充套件:

    如果不想寫任何程式碼,則可以使用 ComponentResourceKey 標記擴充套件。

    1、使用 ComponentResourceKey 為資源建立鍵名,這可起到通知 WPF 我們將在程式集之間共享資源。

    2、使用這種方式時,我們務必將資源字典整合到 Generic.xaml 檔案中,並且必須將該檔案位於 Themes 資料夾中。

      目錄結構大概是這樣的:ResourceDictionaryLibrary/Themes/Generic.xaml

      更合了資源字典的 Generic.xaml 檔案大致是這樣的:

複製程式碼

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

    <ResourceDictionary.MergedDictionaries>
        <!--該資源是要使用在其他程式集中,因此使用下面的 pack URI 語法在其他程式訪問該資源時才能正常執行。如果直接指定資原始檔名稱,則程式將會在自己的資源中查詢。-->
        <ResourceDictionary Source="ResourceDictionaryLibrary;component/ButtonBackgroundDic.xaml"/>
    </ResourceDictionary.MergedDictionaries>

</ResourceDictionary>

複製程式碼

    3、為需要共享的資源建立鍵名。

      使用 ComponentResourceKey 時,需要提供兩部分資訊:類庫程式集中類的引用和描述性的資源ID。類引用是共享資源的關鍵。當在使用時,需要提供相同的類引用和資源ID。

      該類無所謂定義為什麼名,也可以沒有任何程式碼。但是,需要將該類定義到 ComponentResourceKey 將要從中查詢資源的程式集(如我們單獨建立的資源字典的程式集),比如我將該類定義成如下樣子:

public class CustomResources
{
}

    4、使用上面的 CustomResources 類和資源ID建立鍵名:

x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:CustomResources},ResourceId=BtnBackgound_SkyBlue}"

    5、在其他應用程式中的使用:

      • 在使用的地方定義資源類庫程式集的字首,如下所示:
xmlns:res="clr-namespace:ResourceDictionaryLibrary;assembly=ResourceDictionaryLibrary"
      • 使用包含 ComponentResourceKey 的 DynamicResource 呼叫資源。此時的 ComponentResourceKey 就是資源類庫中定義的 ComponentResourceKey 。如下程式碼所示:
<Button Name="btn" Background="{DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type res:CustomResources},ResourceId=BtnBackgound_SkyBlue}}"/>

      注:使用 ComponentResourceKey 時,必須使用動態資源,而不能使用靜態資源。

      • 為了簡化使用方式,可以在提供資源的類庫程式集的類中定義一個靜態屬性,讓其返回正確的 ComponentResourceKey ,如下所示:

 

複製程式碼

public class CustomResources
{

      /// <summary>
      /// 屬性名不必與 ComponentResourceKey 的 resourceId 相同
      /// </summary>

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

複製程式碼

 

      此時,可以使用 Static 標記擴充套件訪問該屬性了並應用資源了,程式碼如下:

<Button Name="btn" Background="{DynamicResource {x:Static res:CustomResources.BtnBackgound_SkyBlue}}"/>