Resource Dictionary –资源字典

所有的资源项在最终都会被整合到Resource Dictionary中的,也就是说无论是FrameworkElement的Resources,还是Window的Resources,还是Application的Resources,还是特定的ResourceDictionary中定义的resources在整个应用编译执行的时候实际上他们都在一起的作为可遍历集合共同存在于一个相对会话空间内的。

我们也提到过Resource的key是可以被允许有相同的,这样在遍历不同相对地址的Resource Dictionary时会根据StaticResource或者DynamicResource的lookup behavior来确定哪个有效。通常为了维护和灵活性的考虑,我们通常会将Resource Dictionary文件分成好几个,但在某些场合下我们只需要用其中某些资源,那么我么可以将资源从几个独立的文件中提取并合并,那么可以这么做:

<Window.Resources>

    <ResourceDictionary>

        <ResourceDictionary.MergedDictionaries>

            <ResourceDictionary Source="Diction1.xaml"></ResourceDictionary>

            <ResourceDictionary Source="Diction2.xaml"></ResourceDictionary>

        </ResourceDictionary.MergedDictionaries>

    </ResourceDictionary>

    </Window.Resources>

Localization – 本地化

本地化和换肤其实都是在用ResourceDictionary来做文章的。说白了,Localization就是用不同语言下取不同事先设定好的资源来显示而已。要做到这些很容易,4步就可以轻松实现:

  • 定义Resource Dictionary来包含不同语言下要显示的资源项。

创建单独的Resource Dictionary文件,并以语言本身名字来命名,并把en-US来作为默认语言环境(这里顺便就命名为default.xaml了)

Default.xaml

<ResourceDictionary 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">

   

    <sys:String x:Key="Title_PM">Project Manager</sys:String>

    <sys:String x:Key="Title_PL">Project Lead</sys:String>

    <sys:String x:Key="Title_SD">Senior Developer</sys:String>

    <sys:String x:Key="Title_SA">System Architecture</sys:String>

   

</ResourceDictionary>

zh-CN.xaml (注意对.NET命名空间的引用)

<ResourceDictionary 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">

 

    <sys:String x:Key="Title_PM">项目经理</sys:String>

    <sys:String x:Key="Title_PL">项目主管</sys:String>

    <sys:String x:Key="Title_SD">资深开发工程师</sys:String>

    <sys:String x:Key="Title_SA">系统架构师</sys:String>

 

</ResourceDictionary>

·         给应用程序添加默认资源:其实就是将默认的Resource Dictionary加入到Application的全局Resource里边。

<Application x:Class="WpfApplication1.App"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    StartupUri="Window1.xaml">

    <Application.Resources>

       

        <ResourceDictionary>

            <ResourceDictionary.MergedDictionaries>

                <ResourceDictionary Source="Language\default.xaml"/>

            </ResourceDictionary.MergedDictionaries>

        </ResourceDictionary>

 

    </Application.Resources>

</Application>

  在Application启动时根据不同语言来加载以语言命名的XAML文件(Resource Dictionary)。因为对于重名的资源,后来加载的资源将会胜出,所以以当前语言名加载的XAML文件中的资源项将会被引用。这就是多语言的本质!

public partial class App : Application

    {

        protected override void OnStartup(StartupEventArgs e)

        {

            base.OnStartup(e);

           

            LoadLanguage();

        }

 

        private void LoadLanguage()

        {

            CultureInfo currentCultureInfo = CultureInfo.CurrentCulture;

            ResourceDictionary langRd = null;

            try

            {

                langRd = Application.LoadComponent(

                new Uri(@"Language\" + currentCultureInfo.Name + ".xaml", UriKind.Relative)) as ResourceDictionary;

            }

            catch

            {

            }

 

            if (langRd != null)

            {

                if (this.Resources.MergedDictionaries.Count > 0)

                {

                    this.Resources.MergedDictionaries.Clear();

                }

                this.Resources.MergedDictionaries.Add(langRd);

            }

        }

    }

在XAML中引用资源。

<TextBlock Canvas.Top="50" Width="100" Height="24" Text="{StaticResource Title_PM}" />

 大功告成,运行程序你会看到默认的语言的显示:Project Manager.当然如果你的默认文化是英语的话。用程序换成中文试试结果?没问题,在LoadLanguage()之前更改语言即可:

 

base.OnStartup(e);(就是写在application的OnStartup事件里)

CultureInfo info = new CultureInfo("zh-CN");

Thread.CurrentThread.CurrentCulture = info;

Thread.CurrentThread.CurrentUICulture = info;

LoadLanguage();