App.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="Language" value="zh-CN"/>
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
</configuration>
App.xaml
<Application x:Class="TestTool.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestTool"
StartupUri="MainWindow.xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
d1p1:Ignorable="d"
xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006">
<Application.Resources>
<ResourceDictionary>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:MMITestTool.ViewModel" />
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml"/>
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
App.xaml.cs
public partial class App : Application
{
public App()
{
InitLog();
}
protected override void OnStartup(StartupEventArgs e)
{
this.DispatcherUnhandledException += App_DispatcherUnhandledException;
this.Dispatcher.UnhandledExceptionFilter += Dispatcher_UnhandledExceptionFilter;
this.Dispatcher.UnhandledException += Dispatcher_UnhandledException;
LanguageService.Init();
base.OnStartup(e);
}
private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
Log.Error("[App_DispatcherUnhandledException] " + e?.Exception);
e.Handled = true;
}
private void Dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
Log.Error("[Dispatcher_UnhandledException] " + e?.Exception);
e.Handled = true;
}
private void Dispatcher_UnhandledExceptionFilter(object sender, DispatcherUnhandledExceptionFilterEventArgs e)
{
Log.Error("[Dispatcher_UnhandledExceptionFilter] " + e?.Exception);
}
private void InitLog()
{
// 创建全局静态实例
Log.Logger = new LoggerConfiguration()
//设置最低等级
.MinimumLevel.Verbose()
//将事件发送到文件
.WriteTo.File(@".\Log\Log.txt", /*日志文件名*/
outputTemplate: /*设置输出格式,显示详细异常信息*/
@"{Timestamp:yyyy-MM-dd HH:mm-ss.fff }[{Level:u3}] {Message:lj}{NewLine}{Exception}",
rollingInterval: RollingInterval.Day, /*日志按日保存*/
rollOnFileSizeLimit: true, /*限制单个文件的最大长度*/
encoding: Encoding.UTF8, /*文件字符编码*/
retainedFileCountLimit: 10, /*最大保存文件数*/
fileSizeLimitBytes: 10 * 1024) /*最大单个文件长度*/
.CreateLogger();
}
}
MainViewModel.cs
public class LanguageModel
{
public string Key { get; set; }
public string Value { get; set; }
}
public class MainViewModel : ViewModelBase
{
private string _version;
public string Version
{
get { return _version; }
set { Set(() => Version, ref _version, value); }
}
#region 多语言
private Dictionary<string, string> _languageDic = new Dictionary<string, string>();
private Dictionary<string, string> _languageLoadedDictionary = new Dictionary<string, string>();
private string LanguagesDirectory
{
get
{
var languagesFolder = System.IO.Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Languages");
if (!Directory.Exists(languagesFolder))
{
try
{
Directory.CreateDirectory(languagesFolder);
}
catch (Exception)
{
}
}
return languagesFolder;
}
}
private List<LanguageModel> _languageCollection = new List<LanguageModel>();
public List<LanguageModel> LanguageCollection
{
get { return _languageCollection; }
set { Set(() => LanguageCollection, ref _languageCollection, value); }
}
private LanguageModel _selectedComboBoxItem;
public LanguageModel SelectedComboBoxItem
{
get { return _selectedComboBoxItem; }
set { Set(() => SelectedComboBoxItem, ref _selectedComboBoxItem, value); }
}
public RelayCommand<LanguageModel> ComboBoxSelectionChangedCommand { get; set; }
private void ComboBoxSelectionChangedAction(LanguageModel languageModel)
{
SelectedComboBoxItem = languageModel;
//string language = LanguageService.GetLanguageByLanguageId(menuItem.Name.Trim('_')).Name;
LanguageService.SetLanguageType(SelectedComboBoxItem.Key);
AppConfigManager.SetValue("Language", SelectedComboBoxItem.Key);
}
private void LoadLanguages()
{
_languageLoadedDictionary.Clear();
//清空菜单项
LanguageCollection.Clear();
GetValidLanguages();
//动态加载语言菜单
foreach (var languageItem in _languageLoadedDictionary)
{
if (string.IsNullOrWhiteSpace(languageItem.Key) || string.IsNullOrWhiteSpace(languageItem.Value))
{
continue;
}
LanguageCollection.Add(new LanguageModel() { Key = languageItem.Key, Value = languageItem.Value });
}
SelectedComboBoxItem = LanguageCollection.FirstOrDefault(x => x.Key == LanguageService.CurrentLanguage);
}
private void GetValidLanguages()
{
if (!Directory.Exists(LanguagesDirectory))
{
return;
}
DirectoryInfo directoryInfo = new DirectoryInfo(LanguagesDirectory);
FileInfo[] fileInfos = directoryInfo.GetFiles("*.xaml");
if (fileInfos == null)
{
return;
}
foreach (FileInfo fileInfo in fileInfos)
{
ResourceDictionary info = new ResourceDictionary() { Source = new Uri(fileInfo.FullName) };
string languageCodeid = "LanguageCode";
string languageKeyid = "LanguageID";
string languageNameKeyid = "LanguageName";
if (!info.Contains(languageCodeid) || !info.Contains(languageKeyid) || !info.Contains(languageNameKeyid))
{
continue;
}
string languageName = info[languageNameKeyid].ToString().Trim();
if (!_languageDic.ContainsKey(info[languageKeyid].ToString()))
{
_languageDic.Add(info[languageKeyid].ToString(), languageName);
}
if (!_languageLoadedDictionary.ContainsKey(info[languageCodeid].ToString()))
{
_languageLoadedDictionary.Add(info[languageCodeid].ToString(), languageName);
}
}
}
#endregion
public MainViewModel()
{
ComboBoxSelectionChangedCommand = new RelayCommand<LanguageModel>(ComboBoxSelectionChangedAction);
LanguageService.SetLanguageType(AppConfigManager.GetValue("Language"));
//加载语言菜单
LoadLanguages();
Version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
}
}
AppConfigManager.cs
public class AppConfigManager
{
private static Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
public static void SetConfig(string exeConfigFileName)
{
ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = exeConfigFileName;
config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
}
/// <summary>
/// 根据key获取值
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static string GetValue(string key)
{
if (config.AppSettings.Settings.AllKeys.Contains(key))
{
return config.AppSettings.Settings[key].Value;
}
else
{
return string.Empty;
}
}
/// <summary>
/// 根据key获取值
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static bool GetBoolValue(string key)
{
if (config.AppSettings.Settings.AllKeys.Contains(key))
{
try
{
return System.Convert.ToBoolean(config.AppSettings.Settings[key].Value);
}
catch (System.Exception)
{
return false;
}
}
else
{
return false;
}
}
/// <summary>
/// 设置Value值
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public static void SetValue(string key, string value)
{
config.AppSettings.Settings[key].Value = value;
SaveAppConfig();
}
/// <summary>
/// 添加Value值
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public static void AddValue(string key, string value)
{
config.AppSettings.Settings.Add(key, value);
SaveAppConfig();
}
/// <summary>
/// 移除Value值
/// </summary>
/// <param name="key"></param>
public static void RemoveValue(string key)
{
config.AppSettings.Settings.Remove(key);
SaveAppConfig();
}
/// <summary>
/// 保存AppConfig
/// </summary>
public static void SaveAppConfig()
{
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSetings");
}
}
LanguageResourceHelper.cs
public class LanguageResourceHelper
{
// <summary>
/// 查找资源文件字符串
/// </summary>
/// <param name="keyName"></param>
/// <returns></returns>
public static string FindKey(string keyName)
{
try
{
if (keyName == null || keyName.ToUpper() == "NULL" || string.IsNullOrEmpty(keyName))
return "";
//当错误代码为-1时,就返回“错误代码:-1”
if (keyName == "-1")
keyName = "ErrorCode";
var keyValue = (string)Application.Current.FindResource(keyName);
keyValue += keyName == "-1" ? ":-1" : "";
return keyValue;
}
catch (Exception)
{
return "";
}
}
}
LanguageService.cs
public class LanguageService
{
private static string _languageDirectoryPath = string.Format("{0}Languages", AppDomain.CurrentDomain.SetupInformation.ApplicationBase);
private static Dictionary<string, ResourceDictionary> _allLanguageResource = new Dictionary<string, ResourceDictionary>();
public static string CurrentLanguage;
private static ResourceDictionary _currentLanguage;
private static ResourceDictionary _defaultLanguage;
public static void Init() { }
static LanguageService()
{
LoadAllLanguageResource();
InsertDefaultLanguage();
_currentLanguage = _defaultLanguage;
}
/// <summary>
/// 动态切换播放器语言设置
/// </summary>
/// <param name="fileName">资源文件名 en-US或zh-CN</param>
public static void SetLanguageType(string culture)
{
if (!_allLanguageResource.ContainsKey(culture)) // 语言不存在,则使用默认语言
{
return;
}
if (_currentLanguage != null && _currentLanguage != _defaultLanguage && Application.Current.Resources.MergedDictionaries.Contains(_currentLanguage))
{
Application.Current.Resources.MergedDictionaries.Remove(_currentLanguage);
}
_currentLanguage = _allLanguageResource[culture];
Application.Current.Resources.MergedDictionaries.Add(_currentLanguage);
CurrentLanguage = culture;
}
static void LoadAllLanguageResource()
{
if (_allLanguageResource.Count > 0)
{
return;
}
string languagesForder = System.IO.Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Languages");
if (!Directory.Exists(languagesForder))
{
return;
}
DirectoryInfo directoryInfo = new DirectoryInfo(languagesForder);
FileInfo[] fileInfos = directoryInfo.GetFiles("*.xaml");
if (fileInfos == null)
{
return;
}
foreach (FileInfo fileInfo in fileInfos)
{
ResourceDictionary info = new ResourceDictionary() { Source = new Uri(fileInfo.FullName) };
string languageKeyid = "LanguageID";
if (!info.Contains(languageKeyid))
{
continue;
}
var language = GetLanguageByLanguageId(info[languageKeyid].ToString());
if (language == null)
{
continue;
}
if (!_allLanguageResource.ContainsKey(language.Name))
{
_allLanguageResource.Add(language.Name, info);
}
}
}
private static void InsertDefaultLanguage()
{
_defaultLanguage = new ResourceDictionary() { Source = new Uri("TestTool;component/Languages/English.xaml", UriKind.RelativeOrAbsolute) };
Application.Current.Resources.MergedDictionaries.Insert(0, _defaultLanguage);
}
/// <summary>
/// Gets the value.
/// </summary>
/// <param name="key">The key.</param>
/// <returns></returns>
public static string GetValue(string key)
{
if (string.IsNullOrEmpty(key))
return string.Empty;
object value = GetValue(key);
if (value == null)
return string.Empty;
return value.ToString();
}
public static CultureInfo GetLanguageByLanguageId(string languageID)
{
CultureInfo[] allCultureInfos = CultureInfo.GetCultures(CultureTypes.SpecificCultures);
foreach (CultureInfo cultureInfo in allCultureInfos)
{
if (string.Compare(cultureInfo.LCID.ToString(), languageID) == 0)
{
return cultureInfo;
}
}
return null;
}
}
English.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<sys:String x:Key="LanguageCode">en-US</sys:String>
<sys:String x:Key="LanguageID">1033</sys:String>
<sys:String x:Key="LanguageName">English</sys:String>
<sys:String x:Key="LanguageSetting">Language</sys:String>
<sys:String x:Key="User_ID">User ID:</sys:String>
<sys:String x:Key="User_Name">User Name:</sys:String>
</ResourceDictionary>