在XAML中使用占位符进行WPF本地化扩展

时间:2016-08-24 12:32:59

标签: wpf xaml wpflocalizationextension

我在我的程序中使用WPF Localization Extension。 为了减少类似资源的数量(例如"以米为单位的长度","以公里为单位的长度"等等)我想使用占位符并在XAML代码中设置它们。

我想过这样的事情

资源的价值" UI_Length"

Length in {0}

在CodeBehind中,使用String.Format

非常容易
String.Format(
        LocalizeDictionary.Instance.GetLocalizedObject("UI_Length", null, LocalizeDictionary.Instance.Culture).ToString(), 
       "Meters");

但是如何在XAML中添加另一个String甚至是另一个资源条目?

<Label x:Name="Label" Content="{lex:LocText Key=UI_Length}, Meters" HorizontalAlignment="Left" VerticalAlignment="Top"/>

根据Binding placeholder from resource file in WPF,它似乎是可能的,但我无法让它运行标签

[更新]

我设法添加了两个资源值。 诀窍是在Label.Content中添加一个TextBlock。 see Link

        <Label  Grid.Row="1">
            <Label.Content>
                <TextBlock>
                    <TextBlock.Text>
                        <MultiBinding StringFormat="{}{0} [{1}]">
                            <Binding Source="{lex:LocText Key=UI_Length}" />
                            <Binding Source="{lex:LocText Key=UI_MeterShort}" />
                        </MultiBinding>
                    </TextBlock.Text>
                </TextBlock>
            </Label.Content>
        </Label>

但我在这里仍有问题。在启动时,这工作正常,但当我尝试切换语言时

LocalizeDictionary.Instance.Culture = new CultureInfo("de-DE");

我得到一个&#34;绑定在使用后无法更改。&#34;错误。 有没有类似的方法来使用几个资源值,并且仍然能够在运行时切换语言?

[更新2]

我尝试了Liero的建议,但仍然有问题。

在我的MainView中,我将DataContext设置为MainViewModel。 VM具有LocalizedTexts的实例。在ViewModel中更改语言后,我调用了RaisePropertiesChanged(),但我没有得到任何输出。

TextBlock绑定到LengthInMeters

<TextBlock Text="{Binding LocalizedTexsts.LengthInMeters}" />

我在更改语言后调用了RaisePorpertyChanged:

    public void ChangeLanguage(string culture)
    {
         LocalizeDictionary.Instance.Culture = new CultureInfo(culture);
         _localizedTexts.RaisePropertyChanged();
    }

LengthInMeters看起来像这样:

public string LengthInMeters
{
    get
    {
        return String.Format(
                   LocalizeDictionary.Instance.GetLocalizedObject(
                       "UI_Length", null,
                       LocalizeDictionary.Instance.Culture).ToString(),
                   LocalizeDictionary.Instance.GetLocalizedObject(
                       "UI_Meters", null,
                       LocalizeDictionary.Instance.Culture).ToString()
               );
    }
}

但TextBlock保持空白。

1 个答案:

答案 0 :(得分:3)

首先,您可以像这样缩短绑定:

<TextBlock Text="{Binding Source={lex:LocText Key=UI_MeterShort}, 
                          StringFormat={lex:LocText Key=UI_Length}}" />

其次,如果要更新绑定,当语言更改时,则需要在代码隐藏中找到TextBlock并使用BindingExpression.UpdateTarget()方法手动更新绑定。但那很奇怪,不是吗?

或者,您可以通过删除所有内容并创建新内容来刷新整个窗口。我的意思是从窗口中删除UserControl并创建新的UserControl。

然而,这两种解决方案都很奇怪,因为它只是解决了因滥用WPF中的绑定而导致的问题。让我建议更好的方法。

public class LocalizedTexts: INotifyPropertyChanged
{
   public event PropertyChanged;


   public LengthInMeters { get { return String.Format(...); } }

   public LengthInKilometers {get { return String.Format(...); } }


   public void RaisePropertiesChanged()
   {
      foreach (var property in this.GetType().GetProperties())
      {
         PropertyChanged(this, new PropertyChangedEventArgs(property.Name))
      }
   }
}

现在您可以数据绑定到LocalizedTexts,当语言发生变化时,只需调用RaisePropertiesChanged()

用法:

<Application.Resources>
    <l:LocalizedTexts x:Key="LocalizedTexts" />
</Application.Resources>

<TextBlock Text="{Binding LengthInMeters, Source={StaticResource LocalizedTexts}}" />


<!-- instead of using StaticResource, you can add l:LocalizedTexts  as a property to your viewmodel -->
<TextBlock Text="{Binding LocalizedTexts.LengthInMeters}" />