WPF的资源续集

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中引用到,我们需要改变一下编译资源文件时使用的工具,如下图:

image

右键资源文件,在属性时把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

你可能感兴趣的:(WPF)