1. 兩種資源檔的串連
前面講了.net中使用資源的通用方法,以及WPF中對UI進行Localization的方法,在實際使用中,經常會同時使用兩種方法,我們需要用al.exe這個工具,把兩個資源檔連結成一個資源檔:
al /template:WpfLocalizationLocBaml.exe
/embed:de\WpfLocalizationLocBaml.g.de.resources
/embed:..\obj\WpfLocalization.Properties.Resources.de.resources
/culture:de /out:de\WpfLocalizationLocBaml.resources.dll
WpfLocalizationLocBaml.g.de.resources是利用LocBaml產生的檔案,可以在obj\Debug中找到,或者用LocBaml產生也可以:
LocBaml.exe /generate ..\..\obj\WpfLocalizationLocBaml.g.de.resources
/trans:..\..\Res\de.csv
WpfLocalization.Properties.Resources.de.resources 是工程中Properties檔案夾下的資源檔。
最終會產生一個WpfLocalizationLocBaml.resources.dll ,要把它放到相應語言的檔案夾下,這裡是de。
2. 在Xaml中使用.net通用資源
預設的,Visual Studio產生的資源檔對應的cs檔案中的類是internal的,不能在xaml中引用到,我們需要改變一下編譯資源檔時使用的工具,如:
右鍵資源檔,在屬性時把ResXFileCodeGenerator改為PublicResXFileCodeGenerator(在2005的時代,這個工具叫ResXFileCodeGeneratorEx),這樣產生的cs檔案的類就是pulic了,最好再檢查一下,避免某些誤操作把cs檔案清空了。
<Window x:Class="WpfLocalization1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="WPF_Localize" Height="155" Width="194" xmlns:prop="clr-namespace:WpfLocalization1.Properties"> <Grid> <Button Margin="30,20,35,26" Name="button1" Content="{x:Static prop:Resources.MainButtonText}" /> </Grid></Window>
在xaml中加入Properties的命名空間,就可以利用StaticExtension得到資源檔中對應的值,如上段代碼。
3. 在xaml中定義Resource
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="Simple Window"> <Window.Resources> <SolidColorBrush x:Key="backgroundBrush">Yellow</SolidColorBrush> <SolidColorBrush x:Key="borderBrush">Red</SolidColorBrush> </Window.Resources> <Window.Background> <StaticResource ResourceKey="backgroundBrush"/> </Window.Background> <DockPanel> <StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Center"> <Button Background="{StaticResource backgroundBrush}" BorderBrush="{StaticResource borderBrush}" Margin="5"> <Image Height="21" Source="zoom.gif"/> </Button> <Button Background="{StaticResource backgroundBrush}" BorderBrush="{StaticResource borderBrush}" Margin="5"> <Image Height="21" Source="defaultThumbnailSize.gif"/> </Button> <Button Background="{StaticResource backgroundBrush}" BorderBrush="{StaticResource borderBrush}" Margin="5"> <Image Height="21" Source="previous.gif"/> </Button> <Button Background="{StaticResource backgroundBrush}" BorderBrush="{StaticResource borderBrush}" Margin="5"> <Image Height="21" Source="slideshow.gif"/> </Button> <Button Background="{StaticResource backgroundBrush}" BorderBrush="{StaticResource borderBrush}" Margin="5"> <Image Height="21" Source="next.gif"/> </Button> <Button Background="{StaticResource backgroundBrush}" BorderBrush="{StaticResource borderBrush}" Margin="5"> <Image Height="21" Source="counterclockwise.gif"/> </Button> <Button Background="{StaticResource backgroundBrush}" BorderBrush="{StaticResource borderBrush}" Margin="5"> <Image Height="21" Source="clockwise.gif"/> </Button> <Button Background="{StaticResource backgroundBrush}" BorderBrush="{StaticResource borderBrush}" Margin="5"> <Image Height="21" Source="delete.gif"/> </Button> </StackPanel> <ListBox/> </DockPanel></Window>
繼承於FrameworkElement的類都有Resource屬性,其是個ResourceDictionary 類,也就是基於Hasgtable的索引值表。鍵是用x:Key表示。
可以根據不同需求,把Resource放在不同的層級,比如Application層級(在App.xaml中),windows層級,控制項層級。子層級可以引用父層級的Resource,子層級的Resource可以覆蓋父層級的Resource,如果父子同時定義了相同的key,則以子層級為主。
可以把Resource放在不同的檔案中(Visual Studio中右鍵增加Resource Dictionary),可以使用MergeredDictionaries把Resource檔案合并在一起:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="file1.xaml"/>
<ResourceDictionary Source="file2.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
有時需要將FrameworkElement或FrameworkContentElement設定resource,可以設定resource的x:Shared = false,這樣引用的FrameworkElement實際上是不同的複本。
4. StaticResource與DynamicResource
StaticResource通常在windows或page Load時載入,DynamicResource用到時才載入,DynamicResource比StaticResource開銷更大。
DynamicResource只能設定在dependency property上, StaticResource無此限制。
StaticResource要求先聲明才能引用,DynamicResource無此限制。
SystemColors, SystemFonts, SystemParameters這些是系統定義的,可以在控制台中設定,所以要用DynamicResource。
<Button Background="{DynamicResource {x:Static SystemColors.WindowBrush}}"/>
5. C#中使用resource
定義資源:
window.Resources.Add(“backgroundBrush”, new SolidColorBrush(“Yellow”));
window.Resources.Add(“borderBrush”, new SolidColorBrush(“Red”));
StaticResource:
Button button = new Button();
button.Background = (Brush)button.FindResource(“backgroundBrush”);
button.BorderBrush = (Brush)button.FindResource(“borderBrush”);
FindResource沒找到會異常,或者用TryFindResource方法,沒找到返回null
DynamicResource:
Button button = new Button();
button.SetResourceReference(Button.BackgroundProperty, “backgroundBrush”);
button.SetResourceReference(Button.BorderBrushProperty, “borderBrush”);
從這裡可以看到DynamicResource只能在Dependency property上使用。
雖然可以直接使用索引器檢索到資源:
Button button = new Button();
button.Background = (Brush)window.Resources[“backgroundBrush”];
button.BorderBrush = (Brush)window.Resources[“borderBrush”];
但是這種方法是不提倡的,因為直接檢索Resource dictionary,不遍曆邏輯樹狀結構,某些時候會產生非預期效果,當然不遍曆邏輯樹狀結構,效能上有一點點提升。
6. 引用其他assembly中的資源
定義資源:
<SolidColorBrush
x:Key=”{ComponentResourceKey TypeInTargetAssembly={x:Type local:MyClass},
ResourceId=MyClassBrush}”>Yellow</SolidColorBrush>
Key不能使用string了,要使用ComponentResourceKey這個Markup Extension。
使用資源:
<Button Background="{DynamicResource {ComponentResourceKey TypeInTargetAssembly=
otherAssembly:MyClass, ResourceId=MyClassBrush}}"/>
有關WPF使用資源檔可以參見http://www.codeproject.com/KB/WPF/WPFUsingLocbaml.aspx#link_4