文本块绑定属性更改在UWP中不起作用

时间:2019-11-07 10:08:11

标签: c# data-binding uwp localization xamarin.uwp

我正在尝试实现一个简单的“按下按钮以更改App语言和所有相关字符串”的示例。 (您可以在this GitHub repository上查看整个代码)

在此示例中,我有三个TextBlock和一个绑定到我的语言资源的按钮:

Resources hierarchy

并且:

<StackPanel
    HorizontalAlignment="Center"
    VerticalAlignment="Center"
    Orientation="Vertical">

    <TextBlock
        HorizontalAlignment="Center"
        FontSize="20"
        Text="{Binding Source={StaticResource Localized}, Path=[A]}" />
    <TextBlock
        HorizontalAlignment="Center"
        FontSize="20"
        Text="{Binding Source={StaticResource Localized}, Path=[B]}" />
    <TextBlock
        HorizontalAlignment="Center"
        FontSize="20"
        Text="{Binding Source={StaticResource Localized}, Path=[C]}" />

    <Button
        x:Name="btnChangeLanguage"
        Margin="10"
        Padding="10"
        Click="btnChangeLanguage_Click"
        Content="{Binding Source={StaticResource Localized}, Path=[Change]}" />

</StackPanel>

如您所见,我用TextBlock

表示了Text="{Binding Source={StaticResource Localized}, Path=[A]}"的绑定。

已本地化类型LocalizedStrings,它是App类的静态属性:

public class LocalizedStrings : INotifyPropertyChanged
{
    private readonly ResourceLoader _resources;
    private readonly LocalizationHelper _localizationHelper;

    public event PropertyChangedEventHandler PropertyChanged;

    public LocalizedStrings()
    {
        _resources = ResourceLoader.GetForViewIndependentUse();
        _localizationHelper = App.LocalizationHelper;
        _localizationHelper.OnLocalizationChange += _localizationHelper_OnLocalizationChange;
    }

    public string this[string key]
    {
        get
        {
            return _resources.GetString(key);
        }
    }

    private void _localizationHelper_OnLocalizationChange(object sender, System.EventArgs e)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(string.Empty));
    }
}

LocalizationHelper最有趣的部分就是:

public void ChangeLocalizationTo(string cultureCode)
{
    Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = cultureCode;
    OnLocalizationChange?.Invoke(null, new PropertyChangedEventArgs(string.Empty));
}

最后,MainPage按钮的代码:

private void btnChangeLanguage_Click(object sender, RoutedEventArgs e)
{
    if (LocalizationHelper.IsCultureItalian(App.LocalizationHelper.GetCurrentLocalizationCode()))
        App.LocalizationHelper.ChangeLocalizationTo("en-US");
    else App.LocalizationHelper.ChangeLocalizationTo("it-IT");
}

绑定正常工作,但是它们只是第一次绑定 而从未更新。因此,启动应用程序后,我看到了字符串(在设计时也是如此),但是当我按下按钮时,什么也没发生。似乎OnLocalizationChange?.Invoke(null, new PropertyChangedEventArgs(string.Empty));(被称为)不允许应用程序调用属性来获取翻译。 (请注意,我使用string.Empty作为属性名称来通知该类中的所有属性都已更改)

“有趣”的事实是,使用WPF制作的相同示例非常完美!

WPF Example

这使我认为两个平台绑定逻辑有一些不同的行为。

我已经尝试放置一个Mode=OneWay绑定,但是不起作用。

(您可以在this GitHub repository上查看整个代码)

1 个答案:

答案 0 :(得分:2)

修改PrimaryLanguage后,您需要手动刷新页面。请将以下代码添加到btnChangeLanguage_Click方法中。

private void btnChangeLanguage_Click(object sender, RoutedEventArgs e)
{
    if (LocalizationHelper.IsCultureItalian(App.LocalizationHelper.GetCurrentLocalizationCode()))
        App.LocalizationHelper.ChangeLocalizationTo("en-US");
    else App.LocalizationHelper.ChangeLocalizationTo("it-IT");

    //refresh current page
    Frame.Navigate(this.GetType());
}

更新

  

我以为我可以避免依靠绑定来重新加载页面

如果要刷新绑定,可以将页面数据上下文更改为新对象,我们需要像下面这样重新编写xaml绑定。

Xaml

<StackPanel
    HorizontalAlignment="Center"
    VerticalAlignment="Center"
    Orientation="Vertical">

    <TextBlock
        HorizontalAlignment="Center"
        FontSize="20"
        Text="{Binding [A]}" />
    <TextBlock
        HorizontalAlignment="Center"
        FontSize="20"
        Text="{Binding [B]}" />
    <TextBlock
        HorizontalAlignment="Center"
        FontSize="20"
        Text="{Binding [C]}" />

    <Button
        x:Name="btnChangeLanguage"
        Margin="10"
        Padding="10"
        Click="btnChangeLanguage_Click"
        Content="{Binding [Change]}" />

</StackPanel>

隐藏代码

 public MainPage()
 {
     InitializeComponent();
     this.DataContext = new LocalizedStrings();
 }

 private async void btnChangeLanguage_Click(object sender, RoutedEventArgs e)
 {
     if (LocalizationHelper.IsCultureItalian(App.LocalizationHelper.GetCurrentLocalizationCode()))
         App.LocalizationHelper.ChangeLocalizationTo("en-US");
     else App.LocalizationHelper.ChangeLocalizationTo("it-IT");
     await Task.Delay(100); // used to prepare the resource.
     this.DataContext = new LocalizedStrings();
 }