我在我的程序中使用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保持空白。
答案 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}" />