You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何随CurrentCulture更新NotifyIcon与ContentControl的UI?

解决WPF语言切换后模态窗口与NotifyIcon未更新的问题

问题场景

我在MainWindow内有作为模态窗口的ContentControl(用户控件)以及NotifyIcon,通过单选按钮事件切换CurrentCulture。当前切换逻辑如下:

初始化与切换方法代码

// Initialization
public string LangSwitch { get; private set; } = "";

// Language switch method
private void OnEnglishRadioButtonChecked(object sender, RoutedEventArgs e)
{
    LangSwitch = "en-US";
    Close();
}

App.xaml.cs代码

public static void ToggleLanguage(object? sender, EventArgs e)
{
   var window = (MainWindow) sender;
   if (window == null || string.IsNullOrEmpty(window.LangSwitch)) return;

   window.Closed -= ToggleLanguage;
   window.Close();

   var language = window.LangSwitch;
   Thread.CurrentThread.CurrentUICulture = new CultureInfo(language);
   Thread.CurrentThread.CurrentCulture = new CultureInfo(language);
   Settings.Default.LanguageCode = language;
   Settings.Default.Save(); 

   window = new MainWindow();
   window.Show();
}

切换后MainWindow会刷新并更新为当前文化的文本,但模态窗口和NotifyIcon的UI并未更新,仅重启应用后才会生效。尝试过刷新模态窗口Frame、重新初始化NotifyIcon并释放旧实例、设置Frame内容为默认页面,但都无效。

解决方案

1. 模态窗口本地化更新

模态窗口的本地化绑定需要在文化切换时强制刷新资源与绑定,而非依赖CurrentUICulture的静态变化:

// 在模态窗口(用户控件)类中添加以下方法
public void RefreshLocalization()
{
    var culture = Thread.CurrentThread.CurrentUICulture;
    // 重新加载对应文化的资源字典
    this.Resources.MergedDictionaries.Clear();
    var resourceDict = new ResourceDictionary
    {
        Source = new Uri($"Resources/Lang.{culture.Name}.xaml", UriKind.Relative)
    };
    this.Resources.MergedDictionaries.Add(resourceDict);
    // 递归刷新所有控件的绑定
    RefreshVisualTree(this);
}

private void RefreshVisualTree(DependencyObject parent)
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
    {
        var child = VisualTreeHelper.GetChild(parent, i);
        if (child is FrameworkElement element)
        {
            // 刷新常见绑定属性
            element.GetBindingExpression(FrameworkElement.DataContextProperty)?.UpdateTarget();
            element.GetBindingExpression(FrameworkElement.ContentProperty)?.UpdateTarget();
            // 遍历所有绑定属性并刷新
            foreach (var prop in element.GetLocalValueEnumerator())
            {
                if (BindingOperations.GetBinding(element, prop.Property) != null)
                {
                    element.GetBindingExpression(prop.Property)?.UpdateTarget();
                }
            }
        }
        RefreshVisualTree(child);
    }
}
  • 如果模态窗口是已打开的实例,在文化切换后调用RefreshLocalization();
  • 如果是新打开模态窗口,初始化时读取最新CurrentUICulture加载对应资源字典。

2. NotifyIcon本地化更新

修改NotifyIconManager,添加方法重新加载本地化文本并重建右键菜单:

// 在NotifyIconManager类中添加以下方法
public void RefreshNotifyIconLocalization()
{
    var culture = Thread.CurrentThread.CurrentUICulture;
    // 更新提示文本
    notifyIcon.Text = Resources.ResourceManager.GetString("NotifyIconTooltip", culture);
    // 重建右键菜单
    RebuildContextMenu();
}

private void RebuildContextMenu()
{
    notifyIcon.ContextMenuStrip.Items.Clear();
    var culture = Thread.CurrentThread.CurrentUICulture;
    // 根据当前文化重新添加菜单项
    notifyIcon.ContextMenuStrip.Items.Add(
        Resources.ResourceManager.GetString("MenuOpen", culture), 
        null, 
        OnOpenClick
    );
    notifyIcon.ContextMenuStrip.Items.Add(
        Resources.ResourceManager.GetString("MenuExit", culture), 
        null, 
        OnExitClick
    );
}

文化切换完成后,调用NotifyIconManager.Instance.RefreshNotifyIconLocalization()即可更新文本。

3. 优化整体切换逻辑

放弃关闭重启MainWindow的方式,直接在当前上下文刷新所有UI:

// 修改App.xaml.cs的ToggleLanguage方法
public static void ToggleLanguage(string languageCode)
{
    var culture = new CultureInfo(languageCode);
    Thread.CurrentThread.CurrentUICulture = culture;
    Thread.CurrentThread.CurrentCulture = culture;
    Settings.Default.LanguageCode = languageCode;
    Settings.Default.Save(); 

    // 刷新主窗口(需给MainWindow添加类似的RefreshLocalization方法)
    var mainWindow = Application.Current.MainWindow as MainWindow;
    mainWindow?.RefreshLocalization();

    // 刷新所有已打开的模态窗口
    foreach (Window window in Application.Current.Windows)
    {
        if (window != mainWindow && window is YourModalWindow modalWindow)
        {
            modalWindow.RefreshLocalization();
        }
    }

    // 刷新NotifyIcon
    NotifyIconManager.Instance.RefreshNotifyIconLocalization();
}

修改单选按钮事件:

private void OnEnglishRadioButtonChecked(object sender, RoutedEventArgs e)
{
    App.ToggleLanguage("en-US");
}

效果说明

修改后无需重启MainWindow,语言切换时会即时刷新主窗口、模态窗口及NotifyIcon的本地化文本,无需重启应用即可生效。

内容的提问来源于stack exchange,提问作者White_Wolf_DD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 04:35:52