【问题标题】:Textblock binding property changed not working in UWP文本块绑定属性更改在 UWP 中不起作用
【发布时间】:2020-03-03 21:27:49
【问题描述】:

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

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

还有:

<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(s) 的绑定: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 制作的相同示例可以完美运行!

这让我觉得两个平台的绑定逻辑有一些不同的行为。

我已经尝试过绑定Mode=OneWay,但它不起作用。

(你可以在this GitHub repository看到整个代码)

【问题讨论】:

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


    【解决方案1】:

    修改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();
     }
    

    【讨论】:

    • 感谢 Nico,但这是我不想做的,因为我的页面有一些导航参数。我认为我可以通过绑定来避免重新加载页面。
    • 我想,你可以在更改PrimaryLanguage后手动获取数据_resources.GetString()
    • 你的意思是为每一对控件/字符串调用该方法吗?
    • 我已根据您的要求更新了案例回复。
    • 有效!最后一个问题:您认为 WPF 和 UWP 之间为什么会有如此不同的行为?
    猜你喜欢
    • 2017-02-15
    • 2012-11-17
    • 1970-01-01
    • 2015-01-29
    • 1970-01-01
    • 2015-04-10
    • 2018-08-10
    • 2019-02-17
    • 2018-03-15
    相关资源
    最近更新 更多