当我在一个项目中遇到这个挑战时,我通过使用一个简单的类 ResourceLoader 并利用 INotifyPropertyChanged 来解决它。
您可以从任何地方访问Instanceproperty 并改变文化。所有绑定到索引的字符串都会更新。
必须正确设置注入构造函数的ResourceManager 实例。
public class ResourceLoader : INotifyPropertyChanged
{
private readonly ResourceManager manager;
private CultureInfo cultureInfo;
public ResourceLoader(ResourceManager resourceManager)
{
this.manager = resourceManager;
Instance = this;
this.cultureInfo = CultureInfo.CurrentUICulture;
}
public static ResourceLoader Instance { get; private set; }
public string GetString(string resourceName)
{
string stringRes = this.manager.GetString(resourceName, this.cultureInfo);
return stringRes;
}
public string this[string key] => this.GetString(key);
public void SetCultureInfo(CultureInfo cultureInfo)
{
this.cultureInfo = cultureInfo;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(null));
}
public event PropertyChangedEventHandler PropertyChanged;
}
要在应用程序中显示本地化字符串,您需要通过索引器绑定,如下所示:
<Label Text="{Binding [Test], Source={x:Static ResourceLoader.Instance}}" />
由于它现在已绑定,因此当您调用 ResourceLoader.SetCultureInfo 时它应该会更新,因为 Item[] 'PropertyName' 会导致绑定控件重新获取绑定键的值。
更新
如果我说的是假的,我只是测试了它,并且由于某种原因更改的属性不起作用。我在下面添加了一种不同的方法,这与我在生产中使用的方法很接近我敦促您添加某种弱引用“缓存”,而不是包含所有字符串资源的简单列表 (否则它们将被永久保存)
我保留以上供参考。
public class ResourceLoader
{
public ResourceLoader(ResourceManager resourceManager)
{
this.manager = resourceManager;
Instance = this;
this.cultureInfo = CultureInfo.CurrentUICulture;
}
private readonly ResourceManager manager;
private CultureInfo cultureInfo;
private readonly List<StringResource> resources = new List<StringResource>();
public static ResourceLoader Instance { get; private set; }
public StringResource this[string key] {
get { return this.GetString(key); }
}
public StringResource GetString(string resourceName)
{
string stringRes = this.manager.GetString(resourceName, this.cultureInfo);
var stringResource = new StringResource(resourceName, stringRes);
this.resources.Add(stringResource);
return stringResource;
}
public void SetCultureInfo(CultureInfo cultureInfo)
{
this.cultureInfo = cultureInfo;
foreach (StringResource stringResource in this.resources) {
stringResource.Value = this.manager.GetString(stringResource.Key, cultureInfo);
}
}
}
字符串资源:
public class StringResource : INotifyPropertyChanged
{
public StringResource(string key, string value)
{
this.Key = key;
this.Value = value;
}
private string value;
public string Key { get; }
public string Value {
get { return this.value; }
set {
this.value = value;
this.OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
XAML 绑定
<Label Text="{Binding [ResourceKey].Value, Mode=OneWay, Source={x:Static local:ResourceLoader.Instance}}"
/>
更新 2
遇到this link,他们的实现方式与我的第一种方法类似。也许你可以试一试。
更新 3
修正了第一种方法。两人现在都在工作。需要的是this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(null)); 而不是this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(Item[]));