日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

DotNetCore 3.0 助力 WPF本地化

發布時間:2023/12/4 asp.net 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DotNetCore 3.0 助力 WPF本地化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

概覽

隨著我們的應用程序越來越受歡迎,我們的下一步將要開發多語言功能。方便越來越多的國家使用我們中國的應用程序,基于 WPF 本地化,我們很多時候使用的是系統資源文件,可是動態切換本地化,就比較麻煩了。

實現思路

現在我們將要實現的是基于?DotNetCore 3.0?以上版本 and?WPF?桌面應用程序模塊化的多語言功能。動態切換多語言思路:

  • 把所有模塊的資源文件添加到字典集合。

  • 將資源文件里的key,綁定到前臺。

  • 通過通知更改?CurrentCulture?多語言來使用改變的語言文件里的key。

  • 通過綁定?Binding?拼接Path 在輸出。

動態切換

我們先來看實現結果

  • 第一行是我們的主程序的數據展示,用于業務中的本地化

  • 第二行是我們業務模塊A的數據展示

  • 第三行是我們業務模塊B的數據展示

來看一下xaml展示

通過ComboBox選擇來切換語言

搭建模擬業務項目

創建一個WPF App(.NET Core)應用程序

創建完成后,我們需要引入業務A模塊及業務B模塊和業務幫助模塊

使用ResX資源文件

在各個模塊里添加Strings?文件夾用來包含 各個國家和地區的語言文件。

多語言可以參考:https://github.com/UnRunDeaD/WPF---Localization/blob/master/ComboListLanguages.txt

資源文件可以放在任意模塊內,比如業務模塊A ,主程序,底層業務,控件工具集等

創建各個業務模塊資源文件

Strings文件夾可以任意命名

幫助類

封裝到底層供各個模塊調用

public class TranslationSource : INotifyPropertyChanged{public static TranslationSource Instance { get; } = new TranslationSource();private readonly Dictionary<string, ResourceManager> resourceManagerDictionary = new Dictionary<string, ResourceManager>();public string this[string key]{get{Tuple<string, string> tuple = SplitName(key);string translation = null;if (resourceManagerDictionary.ContainsKey(tuple.Item1))translation = resourceManagerDictionary[tuple.Item1].GetString(tuple.Item2, currentCulture);return translation ?? key;}}private CultureInfo currentCulture = CultureInfo.InstalledUICulture;public CultureInfo CurrentCulture{get { return currentCulture; }set{if (currentCulture != value){currentCulture = value;PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(string.Empty));}}}public event PropertyChangedEventHandler PropertyChanged;public void AddResourceManager(ResourceManager resourceManager){if (!resourceManagerDictionary.ContainsKey(resourceManager.BaseName)){resourceManagerDictionary.Add(resourceManager.BaseName, resourceManager);}}public static Tuple<string, string> SplitName(string local){int idx = local.ToString().LastIndexOf(".");var tuple = new Tuple<string, string>(local.Substring(0, idx), local.Substring(idx + 1));return tuple;}}public class Translation : DependencyObject{public static readonly DependencyProperty ResourceManagerProperty =DependencyProperty.RegisterAttached("ResourceManager", typeof(ResourceManager), typeof(Translation));public static ResourceManager GetResourceManager(DependencyObject dependencyObject){return (ResourceManager)dependencyObject.GetValue(ResourceManagerProperty);}public static void SetResourceManager(DependencyObject dependencyObject, ResourceManager value){dependencyObject.SetValue(ResourceManagerProperty, value);}}public class LocExtension : MarkupExtension{public string StringName { get; }public LocExtension(string stringName){StringName = stringName;}private ResourceManager GetResourceManager(object control){if (control is DependencyObject dependencyObject){object localValue = dependencyObject.ReadLocalValue(Translation.ResourceManagerProperty);if (localValue != DependencyProperty.UnsetValue){if (localValue is ResourceManager resourceManager){TranslationSource.Instance.AddResourceManager(resourceManager);return resourceManager;}}}return null;}public override object ProvideValue(IServiceProvider serviceProvider){object targetObject = (serviceProvider as IProvideValueTarget)?.TargetObject;if (targetObject?.GetType().Name == "SharedDp")return targetObject;string baseName = GetResourceManager(targetObject)?.BaseName ?? string.Empty;if (string.IsNullOrEmpty(baseName)){object rootObject = (serviceProvider as IRootObjectProvider)?.RootObject;baseName = GetResourceManager(rootObject)?.BaseName ?? string.Empty;}if (string.IsNullOrEmpty(baseName)){if (targetObject is FrameworkElement frameworkElement){baseName = GetResourceManager(frameworkElement.TemplatedParent)?.BaseName ?? string.Empty;}}Binding binding = new Binding{Mode = BindingMode.OneWay,Path = new PropertyPath($"[{baseName}.{StringName}]"),Source = TranslationSource.Instance,FallbackValue = StringName};return binding.ProvideValue(serviceProvider);}}

前臺綁定

xmlns:ext="clr-namespace:WpfUtil.Extension;assembly=WpfUtil"xmlns:resx="clr-namespace:ModuleA.Strings"ext:Translation.ResourceManager="{x:Static resx:SR.ResourceManager}"

顯示文字

<Label Content="{ext:Loc Test}" FontSize="21" />

后臺實現

根據業務的需要,我們在界面上無法適用靜態文字顯示的,一般通過后臺代碼來完成,對于 code-behind 的變量使用,同樣可以應用于資源字典。

PS: 歡迎各位大佬慷慨指點,有不足之處,請指出!有疑問,請指出,喜歡它,請支持!

下載地址

https://github.com/androllen/WpfNetCoreLocalization

相關鏈接

https://github.com/Jinjinov/wpf-localization-multiple-resource-resx-one-language/blob/master/README.md

總結

以上是生活随笔為你收集整理的DotNetCore 3.0 助力 WPF本地化的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。