前面的記錄有的地方已經用到了資源,本文就來詳細的記錄一下WPF中的資源。我們平時的“資源”一詞是指“資財之源”,是創造人類社會財富的源泉。在計算機程序中,只要是對程序有用的對象都可以統稱資源。不過本文只記錄WPF對象級資源和二進制資源。
一、WPF對象級資源的定義與查找
在WPF中,每一個界面元素都是一個對象,並且都有一個名為Resources的屬性,這個屬性繼承於FrameworkElement類,其類型為ResourceDictionary。由於元素的屬性名是復數形式,所以每一個對象可以擁有多個資源,由於資源的多樣化,獲取到的資源的類型為object類型,所以在獲取到資源時,必要時要進行轉化成符合自己要求的類型;由其類型可以知對象資源是以鍵值對的形式來存儲的,當需要某個資源時,可以通過key索引來獲取。下面看一個小實例:
<Window x:Class="Chapter_08.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" Title="MainWindow" Height="350" Width="525" > <Window.Resources> <ResourceDictionary> <sys:String x:Key="str"> 我是資源 </sys:String> </ResourceDictionary> </Window.Resources> <Grid x:Name="grid"> <TextBlock x:Name="textblock" Text="{StaticResource ResourceKey=str}"/> </Grid> </Window>
在上面代碼中資源為屬性元素,所以<ResourceDictionary>是可以省略掉的,下面是在后台的等效代碼:
this.Resources["str1"] = "我是資源"; this.textblock.Text = this.FindResource("str1") as string;
由於比較簡單,所以不貼效果圖了。下面記錄一下,檢索資源的順序,比如上面的例子,Textblock會先看一下自身有沒有資源的Key為str的,如果沒有發現的話,會繼續沿着邏輯樹往上找(也就是Window上找)。直到發現為止,如果在XAML中沒有找到的話,程序還會在Application.Resources中找找看,如果再沒有的話,那么就說我找不到(拋出異常)。提到“往外找”,如果有web經驗的話,就想起js和css都可以在外面找,來控制頁面的樣式,WPF中完全也可以實現這樣的功能。由於涉及到style,在此僅提一下使用方法:
<Window.Resources> <ResourceDictionary Source="***.xaml"> </Window.Resources>
這個很像html的外聯式寫法。
二、動態資源與靜態資源
我們實際生活中包含可再生資源和非可再生資源。在計算機里面的資源也是有分類的。主要分為靜態資源(StaticResource)和動態資源(DynamicResource)。靜態資源是在程序運行時,直接把資源讀到內存里面,以后就再也不會發生改變;動態資源是可以改變的,具體可以根據情況使用。下面通過簡單的實例來說明其區別:
XAML代碼:
<Window x:Class="Chapter_08.ResourceType" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="ResourceType" Height="150" Width="150" Background="Brown"> <Window.Resources> <sys:String x:Key="DynamicRes">動態資源</sys:String> <sys:String x:Key="StaticRes">靜態資源</sys:String> </Window.Resources> <StackPanel> <TextBox x:Name="txt1" Text="{DynamicResource ResourceKey=DynamicRes}" Margin="10"/> <TextBox x:Name="txt2" Text="{StaticResource ResourceKey=StaticRes}" Margin="10"/> <Button x:Name="btn" Content="資源類型區分" Click="btn_Click_1" Height="25" Margin="5"/> </StackPanel> </Window>
點擊事件代碼:
private void btn_Click_1(object sender, RoutedEventArgs e) { this.Resources["StaticRes"] = "靜態資源發生改變"; this.Resources["DynamicRes"] = "動態資源發生改變"; }
效果如圖1:
圖1
三、二進制資源
和對象級資源一樣,二進制資源也是對象,但是其所在的位置不是在窗體上,一般在項目下的文件夾或者屬性文件件下面。除此之外,因為控件查找資源時,會沿着邏輯樹查找,如果在樹上找不到資源,最后還會在Application.Resources里面找,所以越是靠上面的資源,能利用資源的元素越多。(可以理解為站的越高,越容易被更多的元素看到,因為元素都是往上看的)。 很多時間都有程序用到外部的文件,為了防止操作不當,使文件與程序分離,破壞了程序的完整性,所以讓文件編譯到目標文件中(.exe、.dll文件)以二進制的數據存在,這就是要記錄的二進制資源。如果要添加的資源是字符串而不是文件,那么可以使用應用程序Properties名稱空間中的Resources.resx資源文件,如果是XAML要訪問該資源的話,要把訪問修飾符改為Public。如圖2
如2
在后台代碼調用資源:
Properties.Resources.Password
在XAML中調用形式:
xmlns:prop="clr-namespace:Chapter_08.Properties" Text="{x:Static prop:Resources.Password}"
如果需要改為中文的話,可以直接去資源里面修改。該類資源便於國際化、本地化。除此之外還有一類就是文件型二進制資源。把文件編譯成二進制文件,下面說一下具體的做法,在項目中添加一個文件夾Resources(可以是其他的名字)然后添加現有項,然后設置資源的屬性的生成操作選項為:Resource,且復制到目錄選項為:不復制, 如果不希望以資源的形式使用外部文件,那么生成操作選項為:None,復制到目錄選擇 :始終復制。
一種引用資源是在XAML中引用<Image x:Name="image" Source="Resources/Images/課程表.jpg" Stretch="Fill"/>
另一中引用時在cs后台代碼中引用,其中有絕對路徑和相對路徑之分,下面列出兩種形式:
//Uri imgUri1 = new Uri(@"Resources/Images/課程表.jpg", UriKind.Relative); Uri imgUri1 = new Uri(@"pack://application:,,,/Resources/Images/課程表.jpg", UriKind.Absolute); this.image.Source = new BitmapImage(imgUri1);
其中相對路徑直接寫程序下面的文件夾到文件的路徑,絕對路徑格式為pack://application,,,:[/程序集名][/可選版本號][/文件夾名]/文件名稱。
當然,隨着資源被編譯成二進制文件,所以生成的exe文件也變大了。
四、總結
本文主要記錄了對象資源和二進制資源以及動態資源和靜態資源的區分,可以根據具體情況選擇。本文是讀書筆記,里面難免有理解不對的地方,歡迎討論!下一篇:《深入淺出WPF》筆記——模板篇。