C# 以编程方式更改应用程序语言-UWP

C# 以编程方式更改应用程序语言-UWP,c#,xaml,uwp,multilingual,C#,Xaml,Uwp,Multilingual,我已经为法语和英语创建了资源文件(.resw)。现在我想在加载我的应用程序的第一页时调用“fr”的资源文件。我做了如下的事情。但它显示了一个例外 “System.NullReferenceException:对象引用未设置为 对象的实例” XAML <TextBlock x:Uid="txt_launch3" Grid.Row="4" Padding="7"/> 问题是您在页面中过早调用该方法。在构造函数中,页面尚未分配给它所在的框架。因此,帧仍在那里 您可以将方法调用移动到On

我已经为法语和英语创建了资源文件(
.resw
)。现在我想在加载我的应用程序的第一页时调用“fr”的资源文件。我做了如下的事情。但它显示了一个例外

“System.NullReferenceException:对象引用未设置为 对象的实例”

XAML

<TextBlock x:Uid="txt_launch3" Grid.Row="4"  Padding="7"/>

问题是您在页面中过早调用该方法。在构造函数中,页面尚未分配给它所在的
框架。因此,
仍在那里

您可以将方法调用移动到
OnNavigatedTo
覆盖:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
    string getDeviceDefaultLang = "fr";
    ChangeLanguage2(getDeviceDefaultLang);
}

private void ChangeLanguage2(string language)
{
    try
    {
        ApplicationLanguages.PrimaryLanguageOverride = language;
        Frame.CacheSize = 0;
        Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset();
        Windows.ApplicationModel.Resources.Core.ResourceContext.GetForViewIndependentUse().Reset();
        Frame.Navigate(this.GetType());
    }
    catch (Exception ex)
    {
        string exx = ex.ToString(); //getting System.NullReferenceException            
    }
}
此外,您可以直接访问应用程序的根框架,而不是通过页面的
frame
属性:

private void ChangeLanguage2(string language)
{
    try
    {
        ApplicationLanguages.PrimaryLanguageOverride = language;
        var rootFrame = Window.Current.Content as Frame;
        rootFrame.CacheSize = 0;
        Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset();
        Windows.ApplicationModel.Resources.Core.ResourceContext.GetForViewIndependentUse().Reset();
        rootFrame.Navigate(this.GetType());
    }
    catch (Exception ex)
    {
        string exx = ex.ToString(); //getting System.NullReferenceException            
    }
}
但是,这并不是最优的,因为您实际上是在导航,而当前正在进行导航(原始
MainPage
navigation)

您很可能会调用更改语言来响应用户操作(如单击按钮),而这一切都不再是问题,并且将定义
Frame

更新 最好的解决方案是在
App.xaml.cs
中的
OnLaunched
处理程序中设置语言覆盖:

protected override void OnLaunched(LaunchActivatedEventArgs e)
{
    Frame rootFrame = Window.Current.Content as Frame;

    // Do not repeat app initialization when the Window already has content,
    // just ensure that the window is active
    if (rootFrame == null)
    {
        // Create a Frame to act as the navigation context and navigate to the first page
        rootFrame = new Frame();

        rootFrame.NavigationFailed += OnNavigationFailed;

        if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
        {
            //TODO: Load state from previously suspended application
        }

        // Place the frame in the current Window
        Window.Current.Content = rootFrame;
    }

    if (e.PrelaunchActivated == false)
    {
        if (rootFrame.Content == null)
        {
            ApplicationLanguages.PrimaryLanguageOverride = "fr";
            Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset();
            Windows.ApplicationModel.Resources.Core.ResourceContext.GetForViewIndependentUse().Reset();

            // When the navigation stack isn't restored navigate to the first page,
            // configuring the new page by passing required information as a navigation
            // parameter
            rootFrame.Navigate(typeof(MainPage), e.Arguments);
        }
        // Ensure the current window is active
        Window.Current.Activate();
    }
}

异常发生在哪一行?哪个对象为空?现在没有显示任何异常。但语言没有改变。是不是rootFrame.CacheSize=0;导致了问题?请您在单击按钮后尝试执行该方法,看看它是否有效?但我的目的不同。第一次启动应用程序时,我希望在系统中显示文本的默认语言。问题是,当您在构造函数中调用
导航
时,“newly”创建的页面将首先显示,然后它将被不包含更新语言的旧页面覆盖。您确实需要至少将代码移动到
on导航到
,或者在
App.xaml.cs
中从
OnLaunched
的末尾调用它。此外,如果您想以系统语言显示文本,您应该ldn无需执行任何操作,系统语言是默认语言,您可以使用
PrimaryLanguageOverride
来使用与系统默认语言不同的语言。我已经用一个示例更新了我的答案,说明了如何在第一次导航之前应用该语言,因此甚至不需要进行帧缓存编辑
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
    Frame rootFrame = Window.Current.Content as Frame;

    // Do not repeat app initialization when the Window already has content,
    // just ensure that the window is active
    if (rootFrame == null)
    {
        // Create a Frame to act as the navigation context and navigate to the first page
        rootFrame = new Frame();

        rootFrame.NavigationFailed += OnNavigationFailed;

        if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
        {
            //TODO: Load state from previously suspended application
        }

        // Place the frame in the current Window
        Window.Current.Content = rootFrame;
    }

    if (e.PrelaunchActivated == false)
    {
        if (rootFrame.Content == null)
        {
            ApplicationLanguages.PrimaryLanguageOverride = "fr";
            Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset();
            Windows.ApplicationModel.Resources.Core.ResourceContext.GetForViewIndependentUse().Reset();

            // When the navigation stack isn't restored navigate to the first page,
            // configuring the new page by passing required information as a navigation
            // parameter
            rootFrame.Navigate(typeof(MainPage), e.Arguments);
        }
        // Ensure the current window is active
        Window.Current.Activate();
    }
}