当前位置:首页 » 电脑基础知识

【Windows 10 应用开发】细说文本资源文件(resw)

2017-10-12 06:00 本站整理 浏览(117)

最近,小戏骨版《红楼梦》很是火热,老周一口气看完了9集,一直看到 Surface 的风扇呼呼响。林黛玉和薛宝钗这两个角色都演得不怎么样,倒是演史湘云的娃娃演得不错,老周甚是喜欢。

于是,昨晚就不写代码了,让机器也休息一下。有人会问,看视频能看到发热?是的,一来,南方的天气,虽说秋分已过,但仍然暑气不消;二来嘛,老周是在网页上看的,Flash 那个播放组件,你懂的,特特的耗性能。

好了,F话就不扯太多,今天咱们聊聊 UWP 开发中,一个比较重要,可很多人不当回事的知识点——文本资源。

别以为这个没啥用,当你开发的应用需要多种语言的UI时,就会很TMD有用了。比如有中文版、英文版、法文版、鸡文版、狗语版等。

在 UWP 应用中,文本资源有一类专用的文件来存放,后缀名为.resw,后面那个“w”可能是 Windows 的意思,也可能是 Word 的意思。不管它,反正你知道这类文件是专用于存放文本资源的就可以了。其实啊,resw 文件本质上就是一个 XML 文档,就跟 .net 项目中的 .resx 文件差不多。resw 文件的架构也确实和 .resx 一样,只不过,它只能加入字符串类型的资源条目罢了。

这是纯技术性的玩意儿,你了解老周的,老周向来特特地不喜欢说太多玄之又玄的理论,拿到某个东西,我只要知道它是啥,干啥用,咋用就够了,其实的事情老周不关心。

估计很多学编程的人,也会像老周这样,最迫不及待的,就是马上用用。好,接下来老周就细细说一下。

如何创建文本资源

既然存放文本资源的是一个resw文件,当然是在项目中【新建项】了,这个会用吧,不用我说了,你要是没用 VS 的话,那你还不能开发 UWP 应用,该去学点幼儿园的课程。

在“新建项”窗口中,你会找到一项叫“资源文件”的,如下图。

再次严重强调一下,这个资源文件是放文本内容专用的,不是用来放片子的,记住了,放片子你可以直接以文件形式放到 Assets 目录下,或者你自己建的目录。

老周的演示项目是这样的,先是在项目中建了个叫 TextDecs 的目录,目录名字是随便取的,不动听,请原谅,本来想叫“小薇”的,但担心笔画太多,截图后看不清。然后下面建了两个.resw文件。如下图所示。

你一定猜到了,老周肯定想弄成简体中文版和繁体中文版。对的,你很聪明。为什么不弄英文版呢。是这样的,老周心里一直有一个痛处,当年英语四级考得特别好,差两分才及格,所以心里一直放不下,虽然佛祖也劝了我几次,不要太在意,但有时候还是得在意一下的,毕竟那是一次人生经历。

如果你 UWP 境界比较高,你肯定看出来了,老周你这文件名不对。是的,这个命名待会儿运行的时候,一定会报错的,但为了忽悠大家去看懂,所以我故意写错了。

那么,怎么写才对呢?很 easy ,在语言标记前面加上“lang-”,或者你可以用完整的单词“language-”,修改后就是这样。

你一定又要问了,不是可以不加 lang 的吗,为啥要加呢?是这样的,这里有个规范,分两种情况讨论:

1、对于目录,可以不加,你可以直接这样命名:zh-CN、zh-TW。

2、对于文件,你应该加上 lang,比如:lang-zh-CN、lang-dog-KK。

因为我这个项目只用一个资源文件就够了,所以,我直接在文件名上加语言标记,这是为了节约地球上的氧气。如果你的应用项目需要有 N 个资源文件,例如,你每种语言都要两个资源文件,那你就要建目录了,把语言标记写在目录名上,然后每个目录下的文件名相同即可。就像这样。

-- zh-cn

| -- Res1.resw

| -- Res2.resw

-- zh-hk

| -- Res1.resw

| -- Res2.resw

这样就很直观了。

上面说的是如何安排资源文件,下面咱们聊聊怎么往里面输入资源条目。

在项目中添加.resw 文件后,可以直接双击打开,VS 会使用.net 的资源文件编辑窗口打开。然后,这里头的操作就跟以往的.net 项目一样了。

比如,老周添加了以下内容。

这里重点说说资源项怎么命名,大伙儿看到,我上面的命名,中间有个“.”,这个点是用来指定属性名的。首先,你得确认一下,你的这条资源是要应用到哪个控件上的。比如我这里,名字为 demo1 的资源条目是应用到 TextBox 控件上的,所以整个条目的名字为 demo1.Header ,即,如果UI上某个 TextBox 控件引用了这条资源,那么,就会自动使用该资源条目中的值来填充 TextBox 控件的 Header 属性。

第二个条目中的道理也一样,用该条目中的文本值来填充 TextBox 控件的 PlaceholderText 属性。一样的道理,demo2 的用途一样,其应用目标依然是 TextBox 控件。

demo3 是用到 Button 控件上的,我们都知道,Button 控件有 Content 属性,如果某个按钮引用了 demo3 资源,那么,就会用对应的资源值去填充按钮的 Content 属性。

resw 资源一般可以将能够直接以文本形式赋值的内容来填充控件属性,除了上面说的属性外,像 Width、Height 这些属性也是可以的,比如,你可以添加这样的资源条目。

demo4.Width   -->   700

这里资源条目的名字为 demo4 ,它可以设置控件的宽度为 700。

尽量使用文本内容,或者可以直接转化为文本的值,不要使用过于复杂的内容,复杂对象许多时候用文本无法表示的。

如何引用资源

资源文件做好了,那么如何在XAML代码中引用呢。这里要用到一个叫 uid 的扩展标记。

还是用前面的例子,刚才大伙看到了,老周添加的资源条目分别为 demo1、demo2、demo3,对的,你在要引用资源的控件声明中,直接使用 uid 来指定资源条目的名字就可以了,比如这样。

    <TextBox x:Uid="/Res/demo1"/>
    <TextBox x:Uid="/Res/demo2"/>

这个引用路径是个相对路径,它的写法是:/<resw文件名>/<资源条目名>

但你要注意,书写路径时,不包括文件扩展名,也不包括语言区域标记名。.resw文件名为 Res.lang-zh-hans.resw,所以写uid时,只写 Res 就可以了。

不管你的资源文件放在项目的根目录下,还是嵌套了多少层的子目录,文件夹的路径是不用写的,只写资源文件的名字即可,目录路径被忽略。正因为如此,resw 文件的名字必须在整个项目中是唯一的,因为应用程序在识别时是不管你在哪个目录下的。

如果A目录下有个t.resw,B目录下又有个t.resw,就会冲突。

咱们不妨来试验一下。我们建两个名字相同的资源文件,然后放在不同的目录下(同一目录下当然不能放同名文件的),然后,我们分别在这两个文件中添加一条目,都命名为 item1。如下图所示。

这时候,你发现有两个 Any.resw 文件,然后,按【F5】运行,会得到以下错误。

看到了吧,重复了吧。

这说明,无论 Any.resw 文件放在啥地方,应用程序只识别相对路径 /Any。

现在,我们改一下,把其中一个 Any.resw 文件中的 item1 改为 item2。按照这逻辑,它应该识别为 /Any/item1 和 /Any/item2,这样估计不会重复。

果然,这样修改之后,就可以顺利编译了。

如何运行时改变语言

你可以在如下图所示的应用清单文件编辑器中设置默认语言。

这一般与SDK或VS的语言版本一致,其实,修改这里的默认语言是不能在应用程序中起作用的。比如,我改为 zh-hant,在运行后,并没有显示繁体的UI。

语言与区域的应用优先级相当的复杂,比解剖一头猪还要复杂。既受应用程序设置的影响,也受系统设置的影响。微软的官方文档中,在“全球化与本地化”主题下列了个表格来说明问题,有兴趣的话你可以看看,链接请点这里

我们有一件比较要紧的事,就是在清单文件中指定一下你的应用支持哪些语言,当然,你不做这事也没啥影响,经老周测试,不指定语言列表也照样能扔上应用商店的。

不过嘛,咱们还是负责一点好,老周还是说说如何指定语言列表吧。这个你要做一个诚实的孩子,你应用中定义了几种语言的资源,就写上几个。比如我刚刚那个,我定义了简体中文和繁体中文,所以,我就写上这哥儿俩。

方法是,右击清单文件,执行【查看代码】菜单,清单编辑器中没有相关的位置让你设置,所以就直接手动写了。

找到 Resources 节点,默认的是 x-generate ,这个我也不知道是啥意思,大概跟编译器的语言保持一致吧。因为我们要为自己的应用列个语言清单,所以这个 x-generate 就可以不要了。

我这个示例应用就应当这么写。

  <Resources>
    <!--<Resource Language="x-generate" />-->
    <Resource Language="zh-hant"/>
    <Resource Language="zh-hans"/>
  </Resources>

反正,你做了几种语言的资源,就写上去就OK了。

如果你不想遵守地区语言的应用优先级,那设置应用的UI语言,最好的做法就是自己写代码来干活。此法是最自由,最能体现人格魅力的。

下面老周向各位介绍一些方法,是不是都可行呢,老周是无法保证的。来,咱们试试看。

方法A:XAML 法,这个方法失败率大约为 98%,不信?试试。

        <StackPanel Margin="16" Language="zh-hant">
            <TextBox x:Uid="/Res/demo1"/>
            <TextBox x:Uid="/Res/demo2"/>
            <Button Margin="0,13,0,0" x:Uid="/Res/demo3"/>
        </StackPanel>

我们知道,XAML 继承了 XML 的许多特性,所以,这个 Language 也不例外。运行一下,结果……

呵呵,依然显示简体中文。

方法B:这个方法成功率为 100%,信不信由你。而且非常简单,一行代码就行。

如果不考虑动态切换,这个最好写在APP的 OnLaunched 方法上。

            if (e.PrelaunchActivated == false)
            {
                ApplicationLanguages.PrimaryLanguageOverride = "zh-hant";
                
                if (rootFrame.Content == null)
                {
                  rootFrame.Navigate(typeof(MainPage), e.Arguments);
                }
                // 确保当前窗口处于活动状态
                Window.Current.Activate();
            }

其实就这么一行。

ApplicationLanguages.PrimaryLanguageOverride = "zh-hant";

为什么要写在判断 PrelaunchActivated 属性的代码中呢。别忘了,UWP 有预启动,在预启动时是不显示UI的,所以,只有需要显示界面时再设置语言,这样才有意义。当然,这只是适用于资源文件完全用于UI的情形,如果你要在代码中动态加载一些内容,就不能等正式启动了,应该在应用入口处就加载。

这样一改后,然后运行,你会发现,界面显示为繁体中文了。

因为上面那行代码会强行修改当前应用的语言区域,所以它起作用了。

今天就说到这里,下回咱们说说如何在代码中动态读取资源。

本文示例源码下载