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

发布于 2024-10-31 11:30:27 字数 4632 浏览 10 评论 0原文

我有一个 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 更改为绑定字符串。但是,我尝试了以下方法,但没有任何效果:

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

现在一切都很好!

I have a XAML Window that has a set of strings that are bound to objects like so:

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

This code works fine when I define my ResouceDictionary like this:

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

However, I want to beable to change where the strings are bound from, so I created a module that looks like this:

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

Then I decided I would try changing the Source to a Binding string. However, I've tried the following and none work:

<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}" />

All generate the same error:

ArgumentNullException was thrown on "ResourceDictionary": Value cannot be null.
Parameter name: item

What can I do to get this working?

I should mention that the StarUI namespace is already defined as the following:

xmlns:StarUI="clr-namespace:StarUI"

EDIT:
I found that with the change I made to the module I can get the code to compile and run if I use:

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

However, I still don't have design-time support. Since the module is returning a static item that doesn't need to lookup anything, is there a way to get design-time support here? If not, is there a way to specify in the XAML a static reference for design-time and then they dynamic reference for run-time?

EDIT 2:
What I finally did was to write the XAML specifying the Source statically and then setting the constructor to 'overwrite' that. Since dictionary entries with the same name will be referenced based on the last one added, I can add a dictionary at run-time but still have a dictionary at design-time.

I used the following to localize my code simply, including design-time support and enabling dynamic changing of languages.

In my XAML I included:

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

In my code-behind:

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 is in a Public Module:

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

A sample of my ResourceDictionary XAML is:

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

Then I just access the language string via:

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

Now everything works great!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

暮年 2024-11-07 11:30:27

您需要从 StaticResource 切换到 DynamicResource,因为您的资源无法立即可用。

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

You would need to switch from StaticResource to DynamicResource, since your resource isn't immediately available.

But you cannot using Bindings on the ResourceDictionary properties, as it does not derive from DependencyObject.

青春有你 2024-11-07 11:30:27

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

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

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

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

If you move your localization resources to a separate assembly, then you can still use static resources within your ResourceDictionary files. You will need to add the "assembly" uri to your header ns reference (ie: xmlns:loc="clr-namespace:MyDLL.Strings;assembly=MyDll.Localization").

Then you can use your localization resources as always with no extra code:

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

I always use my localization resources in separate assemblies.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文