WPF-实现多语言的静态(需重启)与动态切换(不用重启)

一、多语言切换(需重启)

1、配置文件添加Key

XML 复制代码
	<appSettings>
		<add key="language" value="zh-CN"/>
	</appSettings>

2、新增附加属性当前选择语言

cs 复制代码
        public CultureInfo SelectLanguage
        {
            get => (CultureInfo)GetValue(SelectLanguageProperty);
            set => SetValue(SelectLanguageProperty, value);
        }

        public static readonly DependencyProperty SelectLanguageProperty =
            DependencyProperty.Register("SelectLanguage", typeof(CultureInfo), typeof(MainWindow));

3、创建资源文件

4、初始化多语言集合

cs 复制代码
        public ObservableCollection<CultureInfo> CultureInfos { get; private set; } = new ObservableCollection<CultureInfo>();

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            var dir =Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            var curs = CultureInfo.GetCultures(CultureTypes.AllCultures);
            foreach (CultureInfo cur in curs)
            {
                if (string.IsNullOrWhiteSpace(cur.Name)) continue;
                string landir = Path.Combine(dir, cur.Name);
                if (Directory.Exists(landir)) CultureInfos.Add(cur);
            }
            if (CultureInfos.Any(cur => cur.Name.Equals("zh-CN", StringComparison.OrdinalIgnoreCase)) is false)
            {
                var cur = curs.FirstOrDefault(c => c.Name.Equals("zh-CN", StringComparison.OrdinalIgnoreCase));
                if (cur != null) CultureInfos.Add(cur);
            }
            SelectLanguage = Thread.CurrentThread.CurrentCulture;
        }

5、切换多语言并更新配置文件

cs 复制代码
        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
            if (e.Property == SelectLanguageProperty)
            {
                if (SelectLanguage == Thread.CurrentThread.CurrentCulture) return;
                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                if (ConfigurationManager.AppSettings["language"] is null)
                    config.AppSettings.Settings.Add("language", SelectLanguage.Name);
                else
                    config.AppSettings.Settings["language"].Value = SelectLanguage.Name;
                config.Save();
                ConfigurationManager.RefreshSection("appSettings");
            }
        }

6、应用程序启动根据配置切换多语言

cs 复制代码
   /// <summary>
   /// App.xaml 的交互逻辑
   /// </summary>
   public partial class App : Application
   {
       protected override void OnStartup(StartupEventArgs e)
       {
           base.OnStartup(e);
          var lan= ConfigurationManager.AppSettings["language"];
           if (!string.IsNullOrWhiteSpace(lan))
           {
               CultureInfo culture = new CultureInfo(lan);
               Thread.CurrentThread.CurrentCulture = culture;
               Thread.CurrentThread.CurrentUICulture = culture;
           }
       }
   }

7、使用

①映射命名空间

XML 复制代码
xmlns:rs="clr-namespace:WpfApp8.Resources"

②示例

XML 复制代码
    <Grid>
        <GroupBox x:Name="gbox">
            <Grid>
                <Button Width="100"
                Height="80"
                Background="LightGray"
                Content="{x:Static rs:SRS.TestLan}" />
                <ComboBox Width="150"
                  Height="50"
                  HorizontalAlignment="Left"
                  VerticalContentAlignment="Center"
                  DisplayMemberPath="NativeName"
                  ItemsSource="{Binding Path=CultureInfos, ElementName=MW}"
                  SelectedItem="{Binding Path=SelectLanguage, ElementName=MW}" />
            </Grid>
        </GroupBox>
    </Grid>

二、多语言切换(无需重启)

安装Nuget包:WpfExtensions.Xaml

1、创建多语言标记扩展基类

cs 复制代码
    /// <summary>
    /// 多语言绑定扩展基类 
    /// </summary>
    /// <typeparam name="T">多语言文件资源类</typeparam>
    [MarkupExtensionReturnType(typeof(object))]
    public class LanguageExtensionBase<T> : MarkupExtension where T : class
    {
        private static readonly ResourceConverter ResourceConverter = new ResourceConverter();
        [ConstructorArgument("Key")]
        public ComponentResourceKey Key { get; set; }

        public LanguageExtensionBase(string key)
        {
            Key = new ComponentResourceKey(typeof(T), key);
        }
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            if (Key == null)
            {
                throw new NullReferenceException("Key cannot be null at the same time.");
            }

            IProvideValueTarget provideValueTarget = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
            if (provideValueTarget == null)
            {
                throw new ArgumentException("The serviceProvider must implement IProvideValueTarget interface.");
            }

            if (provideValueTarget.TargetObject?.GetType().FullName == "System.Windows.SharedDp")
            {
                return this;
            }

            return new Binding("Value")
            {
                Source = new I18nSource(Key, provideValueTarget.TargetObject),
                Mode = BindingMode.OneWay,
                Converter = ResourceConverter
            }.ProvideValue(serviceProvider);
        }
    }

2、添加资源转换器

cs 复制代码
    /// <summary>
    /// 资源转换器
    /// </summary>
    public class ResourceConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Bitmap val = (Bitmap)((value is Bitmap) ? value : null);
            if (val == null)
            {
                Icon val2 = (Icon)((value is Icon) ? value : null);
                if (val2 != null)
                {
                    return ToBitmapSource(val2.ToBitmap());
                }
                return value;
            }
            return ToBitmapSource(val);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }

        [DllImport("gdi32")]
        private static extern int DeleteObject(IntPtr o);
        public ImageSource ToBitmapSource(Bitmap bitmap)
        {
            IntPtr ptr = bitmap.GetHbitmap(); //obtain the Hbitmap
            BitmapSource bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(ptr, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
            DeleteObject(ptr); //release the HBitmap
            return bitmapSource;
        }
    }

3、创建资源文件

4、继承基类创建指定资源文件扩展

cs 复制代码
    /// <summary>
    /// 多语言绑定扩展
    /// </summary>
    [MarkupExtensionReturnType(typeof(object))]
    internal class LanguageExtension : LanguageExtensionBase<Resource>
    {
        public LanguageExtension(string key) : base(key)
        {
        }
    }

5、添加资源文件管理

cs 复制代码
 I18nManager.Instance.Add(Resource.ResourceManager);

6、切换语言

cs 复制代码
var culture = new CultureInfo("en-US");
I18nManager.Instance.CurrentUICulture = culture;
System.Threading.Thread.CurrentThread.CurrentCulture = culture;

7、使用

①映射命名空间到XAML

XML 复制代码
xmlns:Lan="clr-namespace:SqlSugarTest.Lan"

②资源文件中添加多语言资源

③示例

XML 复制代码
                    <GroupBox Header="多语言测试">
                        <Menu Height="NaN" HorizontalAlignment="Center"
                          VerticalAlignment="Center"
                          Background="{x:Null}"
                          FontSize="12" FontWeight="Bold">
                            <MenuItem Margin="3" Padding="10,8"
                                  HorizontalAlignment="Center"
                                  HorizontalContentAlignment="Center"
                                  Header="{Lan:Language MultiLanguage}">
                                <MenuItem Margin="3" Padding="10,5"
                                      Click="MenuItem_Click_CN" Header="CN-中" />
                                <MenuItem Margin="3" Padding="10,5"
                                      Click="Button_Click_EN" Header="US-英" />
                                <MenuItem Margin="3" Padding="10,5"
                                      Header="Test">
                                    <MenuItem Margin="3" Padding="10,5"
                                          Header="111" />
                                    <MenuItem Margin="3" Padding="10,5"
                                          Header="222" />
                                </MenuItem>
                            </MenuItem>
                        </Menu>
                    </GroupBox>
相关推荐
__water38 分钟前
『功能项目』状态模式转换场景【30】
c#·状态模式·unity引擎
語衣5 小时前
C# 数组定义和常用方法
开发语言·c#
界面开发小八哥7 小时前
DevExpress WPF中文教程:如何解决排序、过滤遇到的常见问题?(一)
wpf·界面控件·devexpress·ui开发
ling1s10 小时前
C#基础(5)交错数组*
开发语言·c#
baivfhpwxf202310 小时前
c# Csv文件读写示例,如果文件存在追加写入
开发语言·c#
ling1s14 小时前
C#基础(8)函数
开发语言·c#
我是苏苏17 小时前
C#高级:递归2-根据ID反向递归求其所有的祖先节点信息
前端·ide·c#·.netcore
wangnaisheng17 小时前
【WPF】Border的使用
c#·wpf
月巴月巴白勺合鸟月半18 小时前
HTTP下载文件
网络·网络协议·http·c#
就是有点傻18 小时前
c#中Graphics常用的属性
c#