news 2026/4/24 6:03:43

WPF 国际化(全球化)管理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
WPF 国际化(全球化)管理

resx资源文件

单个resx扩展

using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using System.Windows.Data; using System.Windows.Markup; /// <summary> /// XAML 用法: /// xmlns:ext="clr-namespace:自己的命名空间.Resources" /// {ext:Localize MainPage_Menu_Start} /// Model用法: /// LocalizeExtension.Instance["MainPage_Menu_DataPacking"]; /// </summary> internal sealed class LocalizeExtension : MarkupExtension, INotifyPropertyChanged { public static LocalizeExtension Instance { get; } = new(); public static void ChangeLanguage(CultureInfo ci) { Resources.Langs.Lang.Culture = ci; OnLanguageChanged?.Invoke(); } public static event Action? OnLanguageChanged; private string Key { get; } public string Result => GetString(Key); public string this[string key] => GetString(key); public static string GetString(string key) { return Resources.Langs.Lang.ResourceManager.GetString(key, Resources.Langs.Lang.Culture)?.Replace("\\n", "\n") ?? $"#{key}#"; } private LocalizeExtension() { Key = string.Empty; } public LocalizeExtension(string key) { Key = key; OnLanguageChanged += () => { OnPropertyChanged(nameof(Result)); }; } public override object ProvideValue(IServiceProvider serviceProvider) { var binding = new Binding(nameof(Result)) { Source = this, Mode = BindingMode.OneWay }; return binding.ProvideValue(serviceProvider); } public event PropertyChangedEventHandler? PropertyChanged; private void OnPropertyChanged([CallerMemberName] string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }

多个resx资源扩展

using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.Runtime.CompilerServices; using System.Windows.Data; using System.Windows.Markup; { /// <summary> /// XAML 用法: /// xmlns:ext="clr-namespace:自己的命名空间.Resources" /// 1:{ext:Localize Key=Main_Title, Source=GUI} /// 2:{ext:Localize MainPage_Menu_Start} --默认资源组(Lang) /// Model用法: /// 1:LocalizeExtension.Instance["MainPage_Menu_DataPacking"]; /// 2:LocalizeExtension.Instance["GUI", nameof(Layout.Main_Nav_Title)]; /// </summary> public sealed class LocalizeExtension : MarkupExtension, INotifyPropertyChanged { public static LocalizeExtension Instance { get; } = new LocalizeExtension(); public static event Action? OnLanguageChanged; private const string DefaultSource = "Lang"; private static readonly Dictionary<string, System.Resources.ResourceManager> ResourceManagers = new(StringComparer.OrdinalIgnoreCase) { ["Lang"] = Lang.ResourceManager, ["GUI"] = Layout.ResourceManager, }; public LocalizeExtension(string key) { Key = key; Source = DefaultSource; OnLanguageChanged += RaiseResultChanged; } public LocalizeExtension() { Key = string.Empty; Source = DefaultSource; OnLanguageChanged += RaiseResultChanged; } public string Key { get; set; } = string.Empty; public string Source { get; set; } = DefaultSource; public string this[string key] => GetString(key, DefaultSource); public string this[string source, string key] => GetString(key, source); public string Result => GetString(Key, Source); public override object ProvideValue(IServiceProvider serviceProvider) { var pvt = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; var targetObject = pvt?.TargetObject; var targetProperty = pvt?.TargetProperty; // targetObject 是 Binding,必须返回“对象”,不能返回 BindingExpression if (targetObject is Binding) { return this; } // 正常给 DependencyProperty 赋值,返回内部绑定实现动态刷新 if (targetObject is DependencyObject && targetProperty is DependencyProperty) { var binding = new Binding(nameof(Result)) { Source = this, Mode = BindingMode.OneWay }; return binding.ProvideValue(serviceProvider); } return Result; } public static void ChangeLanguage(CultureInfo culture) { Lang.Culture = culture; Layout.Culture = culture; OnLanguageChanged?.Invoke(); } public static string GetString(string key, string? source = null) { if (string.IsNullOrWhiteSpace(key)) return string.Empty; var src = string.IsNullOrWhiteSpace(source) ? DefaultSource : source; if (!ResourceManagers.TryGetValue(src!, out var rm)) return $"#InvalidSource:{src}#{key}#"; var value = rm.GetString(key, Lang.Culture); return value?.Replace("\\n", "\n") ?? $"#{src}:{key}#"; } public static void RegisterSource(string source, System.Resources.ResourceManager manager) { if (string.IsNullOrWhiteSpace(source)) throw new ArgumentException("source is required.", nameof(source)); ResourceManagers[source] = manager ?? throw new ArgumentNullException(nameof(manager)); } public event PropertyChangedEventHandler? PropertyChanged; private void RaiseResultChanged() { OnPropertyChanged(nameof(Result)); } private void OnPropertyChanged([CallerMemberName] string? propName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName)); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/24 6:00:23

阿里SkillClaw:让 Agent 技能在真实使用中集体进化

当前 LLM Agent&#xff08;如 OpenClaw&#xff09;依赖**可复用的技能&#xff08;Skills&#xff09;**来完成复杂任务。用户从 Skill Hub 安装技能后&#xff0c;Agent 就能调用这些结构化流程来协调工具使用、执行多步推理。 但这里存在一个根本性问题&#xff1a;技能在…

作者头像 李华
网站建设 2026/4/24 5:52:23

东光GEO软件平台

随着人工智能技术的飞速发展&#xff0c;越来越多的企业开始关注如何在AI时代中获得竞争优势。在这个背景下&#xff0c;东光GEO软件平台应运而生&#xff0c;为企业提供了一种全新的优化服务——GEO&#xff08;Generative Engine Optimization&#xff09;&#xff0c;即生成…

作者头像 李华
网站建设 2026/4/24 5:43:34

A2C强化学习在经典游戏Sonic中的实战应用

1. 项目概述&#xff1a;当强化学习遇上经典游戏第一次看到Sonic the Hedgehog&#xff08;音速小子&#xff09;这个经典游戏被用来测试Advantage Actor-Critic&#xff08;A2C&#xff09;算法时&#xff0c;我仿佛回到了90年代抱着游戏手柄的童年。但这次不同&#xff0c;我…

作者头像 李华