boc*_*cko 6 xaml localization xamarin.forms
我正在使用Strings.resx、Strings.de.resx等来本地化Xamarin.Forms应用程序。我需要能够在运行时更改界面语言,并且它(几乎)可以正常工作。
Xamarin产生static class Strings在namespace MyProject.Resources从资源文件和我使用这些值显示在UI字符串。从代码中执行此操作时,它可以完美运行:
await DisplayAlert(Strings.lblConfirmDelete, Strings.lblDeleteMessage, Strings.lblOK, Strings.lblCancel));
Run Code Online (Sandbox Code Playgroud)
问题是 - 当我在运行时更改 UI 文化时,并非所有从 XAML 以这种方式定义的属性都会更新。按钮、标签、条目属性(占位符等)会按原样更改,但 PageTitle、Toolbaritems 和一些其他属性仍保留以前的语言。
我认为其中一些是在首次创建 Page 时填充的,并且不会随着文化(和 UI 文化)的变化而更新。所以,基本上,我需要一种方法来结合{DynamicResource ...}资源的价值。我知道这DynamicResource可以与 Resource 字典一起使用,但这不是存储用于本地化的语言翻译的好方法。
我试过
Text="{DynamicResource {x:Static lr:Strings.lblAddNew}}"
Run Code Online (Sandbox Code Playgroud)
也不工作。
有没有办法动态刷新页面?
我也试过打电话
global::Xamarin.Forms.Xaml.Extensions.LoadFromXaml(this, typeof(MainListPage));
Run Code Online (Sandbox Code Playgroud)
来自该页面的出现事件,但这也不起作用。
有任何想法吗?
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyProject.View"
xmlns:rs="clr-namespace:MMPI"
x:Class="MyProject.MainListPage"
xmlns:lr="clr-namespace:MyProject.Resources"
Title="{x:Static lr:Strings.appName}"
>
<ContentPage.ToolbarItems>
<ToolbarItem
Name="New"
Order="Primary"
Priority="0"
Text="{x:Static lr:Strings.lblAddNew}"
Clicked="New_Clicked"
>
Run Code Online (Sandbox Code Playgroud)
当我在一个项目中遇到这个挑战时,我通过使用一个简单的类ResourceLoader并利用INotifyPropertyChanged.
您可以Instance从任何地方访问该物业并改变文化。所有绑定到索引的字符串都会更新。
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;
}
Run Code Online (Sandbox Code Playgroud)
要在您的应用程序中显示本地化字符串,您需要通过索引器进行绑定,如下所示:
<Label Text="{Binding [Test], Source={x:Static ResourceLoader.Instance}}" />
Run Code Online (Sandbox Code Playgroud)
由于它现在是绑定的,它应该在您调用时更新,ResourceLoader.SetCultureInfo因为Item[]'PropertyName' 导致绑定控件将值重新获取到它们的绑定键。
如果我说的是假话,我只是测试了它,并且由于某种原因更改的属性不起作用。我在下面添加了一种不同的方法,这与我在生产中使用的方法很接近,我敦促您添加某种弱引用“缓存”,而不是包含所有字符串资源的简单列表(否则它们将永远保留) )
我保留以上以供参考。
<Label Text="{Binding [Test], Source={x:Static ResourceLoader.Instance}}" />
Run Code Online (Sandbox Code Playgroud)
字符串资源:
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
XAML 绑定
<Label Text="{Binding [ResourceKey].Value, Mode=OneWay, Source={x:Static local:ResourceLoader.Instance}}"
/>
Run Code Online (Sandbox Code Playgroud)
遇到了这个链接,他们在那里实现了与我的第一种方法类似的方法。也许你可以试一试。
修复了第一种方法。两人现在都在工作。需要的是this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(null));而不是this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(Item[]));
| 归档时间: |
|
| 查看次数: |
9512 次 |
| 最近记录: |