ResourceDictionary源绑定到模块(用于本地化)

时间:2011-04-11 14:43:33

标签: wpf localization binding resourcedictionary

我有一个XAML窗口,它有一组绑定到对象的字符串:

<Label Content="{StaticResource LabelUserName}" HorizontalAlignment="Right" Name="Label1" VerticalAlignment="Center" />

当我像这样定义我的ResouceDictionary时,这段代码工作正常:

<Window.Resources>
    <ResourceDictionary >
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Strings/Strings_en-US.xaml" />
        </ResourceDictionary.MergedDictionaries>
        <ObjectDataProvider x:Key="objLogon" ObjectType="{x:Type StarUtilities:Logon}" />
    </ResourceDictionary>
</Window.Resources>

但是,我希望能够更改绑定字符串的位置,因此我创建了一个如下所示的模块:

Public Module LocalizationChooser
    Public ReadOnly Property GetLocalization As Uri
        Get
            Return New Uri("/Strings/Strings_en-US.xaml", UriKind.Relative)
        End Get
    End Property
End Module

然后我决定尝试将Source更改为Binding字符串。但是,我尝试过以下操作,但没有工作:

<ResourceDictionary Source="{Binding Source={x:Static Member=StarUI:LocalizationChooser.GetLocalization}}" />
<ResourceDictionary Source="{x:Static Member=StarUI:LocalizationChooser.GetLocalization}" />
<ResourceDictionary Source="{Binding Source=StarUI:LocalizationChooser.GetLocalization}" />
<ResourceDictionary Source="{Binding Source=LocalizationChooser, Path=GetLocalization}" />
<ResourceDictionary Source="{Binding Source=StarUI:LocalizationChooser, Path=GetLocalization}" />
<ResourceDictionary Source="{Binding Source={x:Static Member=StarUI:LocalizationChooser.GetLocalization}, Path=GetLocalization}" />
<ResourceDictionary Source="{Binding Source={x:Static Member=StarUI:LocalizationChooser.GetLocalization}, Path=LocalizationChooser.GetLocalization}" />
<ResourceDictionary Source="{Binding Source={x:Static Member=StarUI:LocalizationChooser.GetLocalization}, Path=StarUI:LocalizationChooser.GetLocalization}" />

所有产生相同的错误:

  

在“ResourceDictionary”上抛出了ArgumentNullException:值不能为null   参数名称:item

我能做些什么才能让它发挥作用?

我应该提一下,StarUI名称空间已经定义如下:

xmlns:StarUI="clr-namespace:StarUI"

修改:
我发现,随着我对模块所做的更改,我可以使用以下代码编译和运行:

<ResourceDictionary Source="{x:Static StarUI:LocalizationChooser.GetLocalization}" />

但是,我仍然没有设计时支持。由于模块返回的静态项不需要查找任何内容,有没有办法在这里获得设计时支持?如果没有,有没有办法在XAML中指定设计时的静态引用,然后是运行时的动态引用?

编辑2
我最后做的是编写静态指定Source的XAML,然后将构造函数设置为'覆盖'。由于将根据添加的最后一个引用具有相同名称的字典条目,我可以在运行时添加字典,但在设计时仍然有字典。

我使用以下内容简单地本地化我的代码,包括设计时支持和动态更改语言。

在我的XAML中,我包括:

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary x:Name="LocalizationStrings" Source="/Strings/Strings_en-US.xaml" />
        </ResourceDictionary.MergedDictionaries>
        <ObjectDataProvider x:Key="objLogon" ObjectType="{x:Type StarUtilities:Logon}" />
    </ResourceDictionary>
</Window.Resources>

在我的代码隐藏中:

Public Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.
    Me.Resources.MergedDictionaries.Add(GetLocalization)
End Sub

GetLocation位于公共模块中:

Public ReadOnly Property GetLocalization As ResourceDictionary
    Get
        Dim resourceLocalization As New ResourceDictionary
        resourceLocalization.Source = New Uri("/Strings/Strings_zh-cn.xaml", UriKind.Relative)
        Return resourceLocalization
    End Get
End Property

我的ResourceDictionary 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="ButtonLogon">Logon</sys:String>
    <sys:String x:Key="ButtonCancel">Cancel</sys:String>
    <sys:String x:Key="LabelUserName">User Name:</sys:String>
    <sys:String x:Key="LabelPassword">Password:</sys:String>
    <sys:String x:Key="LabelKey">Decryption Key:</sys:String>
</ResourceDictionary>

然后我只需通过以下方式访问语言字符串:

<Label Content="{DynamicResource LabelUserName}" Name="Label1" />

现在一切都很棒!

2 个答案:

答案 0 :(得分:4)

您需要从StaticResource切换到DynamicResource,因为您的资源不能立即使用。

但是你不能在ResourceDictionary属性上使用Bindings,因为它不是从DependencyObject派生的。

答案 1 :(得分:0)

如果将本地化资源移动到单独的程序集,则仍可以在ResourceDictionary文件中使用静态资源。您需要添加&#34;程序集&#34; uri到你的标题ns引用(即:xmlns:loc="clr-namespace:MyDLL.Strings;assembly=MyDll.Localization")。

然后您可以像往常一样使用本地化资源而无需额外的代码:

<Label Content="{x:Static loc:LocalizationStrings.TitleXXX}" />

我总是在单独的程序集中使用我的本地化资源。