欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

WPF應(yīng)用程序本地化的最佳方法分享

 更新時(shí)間:2023年08月15日 09:38:45   作者:黑夜中的潛行者  
應(yīng)用程序本地化有很多種方式,選擇合適的才是最好的,這篇文章主要為大家介紹了動(dòng)態(tài)資源的方式,可以在不重啟應(yīng)用程序的情況下進(jìn)行資源的切換,需要的可以參考下

應(yīng)用程序本地化有很多種方式,選擇合適的才是最好的。這里只討論一種方式,動(dòng)態(tài)資源(DynamicResource) 這種方式可是在不重啟應(yīng)用程序的情況下進(jìn)行資源的切換,不論是語(yǔ)言切換,還是更上層的主題切換。想要運(yùn)行時(shí)切換不同的資源就必須使用 動(dòng)態(tài)資源(DynamicResource) 這種方式。

圖片是可以使用資源字典進(jìn)行動(dòng)態(tài) binding 的 不要被誤導(dǎo)了

資源文件

確保不同語(yǔ)言環(huán)境中資源 Key 是同一個(gè),且對(duì)用的資源類型是相同的。

在資源比較多的情況下,可以通過(guò)格式化的命名方式來(lái)規(guī)避 Key 沖突。

資源文件的屬性可以設(shè)置成:

生成操作:內(nèi)容

復(fù)制到輸出目錄:如果較新則復(fù)制

上面的操作可以在不重新編譯程序的情況下編輯語(yǔ)言資源并應(yīng)用。

如果不想讓別人更改語(yǔ)言資源則

生成操作:頁(yè)

復(fù)制到輸出目錄:不復(fù)制

英文資源文件 en-US.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="WindowsTitle">MainWindow</sys:String>
    <ImageSource x:Key="icon">pack://SiteOfOrigin:,,,/Icons/en-USicon.png</ImageSource>
    <sys:String x:Key="LanguageButton">LanguageButton</sys:String>
    <sys:String x:Key="LockTime-OneMinute">1 Minute</sys:String>
    <sys:String x:Key="LockTime-FiveMinute">5 Minute</sys:String>
    <sys:String x:Key="LockTime-TenMinute">10 Minute</sys:String>
    <sys:String x:Key="LockTime-FifteenMinute">15 Minute</sys:String>
    <sys:String x:Key="LockTime-ThirtyMinute">30 Minute</sys:String>
    <sys:String x:Key="LockTime-OneHour">1 Hour</sys:String>
    <sys:String x:Key="LockTime-TwoHour">2 Hour</sys:String>
    <sys:String x:Key="LockTime-ThreeHour">3 Hour</sys:String>
    <sys:String x:Key="LockTime-Never">Never</sys:String>
</ResourceDictionary>

中文資源文件 zh-CN.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="WindowsTitle">主窗口</sys:String>
    <ImageSource x:Key="icon">pack://SiteOfOrigin:,,,/Icons/zh-CNicon.png</ImageSource>
    <sys:String x:Key="LanguageButton">語(yǔ)言按鈕</sys:String>
    <sys:String x:Key="LockTime-OneMinute">1 分鐘</sys:String>
    <sys:String x:Key="LockTime-FiveMinute">5 分鐘</sys:String>
    <sys:String x:Key="LockTime-TenMinute">10 分鐘</sys:String>
    <sys:String x:Key="LockTime-FifteenMinute">15 分鐘</sys:String>
    <sys:String x:Key="LockTime-ThirtyMinute">30 分鐘</sys:String>
    <sys:String x:Key="LockTime-OneHour">1 小時(shí)</sys:String>
    <sys:String x:Key="LockTime-TwoHour">2 小時(shí)</sys:String>
    <sys:String x:Key="LockTime-ThreeHour">3 小時(shí)</sys:String>
    <sys:String x:Key="LockTime-Never">永不</sys:String>
</ResourceDictionary>

資源使用

App.xaml

設(shè)置默認(rèn)語(yǔ)言資源,用于在設(shè)計(jì)階段預(yù)覽,并利用 VS 智能提示資源的 Key 防止 Key編寫出錯(cuò)。

<Application
    x:Class="Localization.Core.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Localization.Core"
    StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/I18nResources/en-US.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

主界面布局

<Window
    x:Class="Localization.Core.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:Localization.Core"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:operate="clr-namespace:Localization.Core.Operates"
    Title="{DynamicResource WindowsTitle}"
    Width="800"
    Height="450"
    Icon="{DynamicResource icon}"
    mc:Ignorable="d">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <ComboBox
            x:Name="comLan"
            Width="{Binding SizeToContent.Width}"
            Height="{Binding SizeToContent.Width}"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            SelectedValuePath="Tag"
            SelectionChanged="ComboBox_SelectionChanged">
            <ComboBoxItem Content="中文" Tag="zh-CN" />
            <ComboBoxItem Content="English" Tag="en-US" />
        </ComboBox>
        <StackPanel Grid.Row="1">
            <Button
                Margin="0,50,0,0"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Content="{DynamicResource LanguageButton}" />
            <ComboBox
                x:Name="cmTime"
                Width="120"
                Margin="20"
                VerticalAlignment="Center">
                <ComboBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{operate:ResourceBinding Key}" />
                    </DataTemplate>
                </ComboBox.ItemTemplate>
            </ComboBox>
        </StackPanel>
    </Grid>
</Window>

cs代碼

public partial class MainWindow : Window
{
    ObservableCollection<KeyValuePair<string, int>>? TimeList { get; set; }
    public MainWindow()
    {
        InitializeComponent();
        var lan = Thread.CurrentThread.CurrentCulture.Name;
        comLan.SelectedValue = lan;
        Loaded += MainWindow_Loaded;
    }
    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        TimeList = new ObservableCollection<KeyValuePair<string, int>>()
        {
            new KeyValuePair<string, int>("LockTime-OneMinute", 1),
            new KeyValuePair<string, int>("LockTime-FiveMinute", 5),
            new KeyValuePair<string, int>("LockTime-TenMinute", 10),
            new KeyValuePair<string, int>("LockTime-FifteenMinute", 15),
            new KeyValuePair<string, int>("LockTime-ThirtyMinute", 30),
            new KeyValuePair<string, int>("LockTime-OneHour", 60),
            new KeyValuePair<string, int>("LockTime-TwoHour", 120),
            new KeyValuePair<string, int>("LockTime-ThreeHour", 180),
            new KeyValuePair<string, int>("LockTime-Never", 0),
        };
        cmTime.ItemsSource = TimeList;
        cmTime.SelectedValue = TimeList[0];
    }
    private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (e.AddedItems is null) return;
        LanguageOperate.SetLanguage((e.AddedItems[0] as ComboBoxItem)!.Tag.ToString()!);
    }
}

App.config

language 配置項(xiàng)用于保存用戶選擇的語(yǔ)言類型

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key="language" value=""/>
    </appSettings>
</configuration>

輔助類

語(yǔ)言切換操作類

檢查方法入?yún)ⅲ兄祫t切換到指定的資源,無(wú)值則讀取配置文件中的值,若配置文件中仍無(wú)值,則獲取當(dāng)前線程運(yùn)行的語(yǔ)言環(huán)境,切換到與語(yǔ)言環(huán)境相匹配的資源,如果沒(méi)有找到與之匹配的資源則不做操作。

切換資源之后,將配置文件中的 language 的 value 改為當(dāng)前所選的語(yǔ)言保存并刷新配置文件,直到下次更改。

重寫 Application 類的 OnStartup 方法,在 OnStartup 中調(diào)用 SetLanguage 方法以實(shí)現(xiàn)應(yīng)用程序啟動(dòng)對(duì)語(yǔ)言環(huán)境的判別。

/// <summary>
/// 語(yǔ)言操作
/// </summary>
public class LanguageOperate
{
    private const string KEY_OF_LANGUAGE = "language";
    /// <summary>
    /// 語(yǔ)言本地化
    /// </summary>
    /// <param name="language">語(yǔ)言環(huán)境</param>
    public static void SetLanguage(string language = "")
    {
        if (string.IsNullOrWhiteSpace(language))
        {
            language = ConfigurationManager.AppSettings[KEY_OF_LANGUAGE]!;
            if (string.IsNullOrWhiteSpace(language))
                language = System.Globalization.CultureInfo.CurrentCulture.ToString();
        }
        string languagePath = $@"I18nResources\{language}.xaml";
        if (!System.IO.File.Exists(languagePath)) return;
        var lanRd = Application.LoadComponent(new Uri(languagePath, UriKind.RelativeOrAbsolute)) as ResourceDictionary;
        var old = Application.Current.Resources.MergedDictionaries.FirstOrDefault(o => o.Contains("WindowsTitle"));
        if (old != null)
            Application.Current.Resources.MergedDictionaries.Remove(old);
        Application.Current.Resources.MergedDictionaries.Add(lanRd);
        Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
        configuration.AppSettings.Settings[KEY_OF_LANGUAGE].Value = language;
        configuration.Save();
        ConfigurationManager.RefreshSection("AppSettings");
        var culture = new System.Globalization.CultureInfo(language);
        System.Globalization.CultureInfo.CurrentCulture = culture;
        System.Globalization.CultureInfo.CurrentUICulture = culture;
    }
}

資源 binding 解析類

ComBox 控件通常是通過(guò) ItemSource 進(jìn)行綁定,默認(rèn)情況下是無(wú)法對(duì)綁定的資源進(jìn)行翻譯的。

通過(guò)繼承 MarkupExtension 類 重寫 ProvideValue 方法來(lái)實(shí)現(xiàn),item 綁定 資源的 Key 的解析。

/// <summary>
/// markup extension to allow binding to resourceKey in general case
/// </summary>
public class ResourceBinding : MarkupExtension
{
    #region properties
    private static DependencyObject resourceBindingKey;
    public static DependencyObject ResourceBindingKey
    {
        get => resourceBindingKey;
        set => resourceBindingKey = value;
    }
    // Using a DependencyProperty as the backing store for ResourceBindingKeyHelper.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ResourceBindingKeyHelperProperty =
        DependencyProperty.RegisterAttached(nameof(ResourceBindingKey),
            typeof(object),
            typeof(ResourceBinding),
            new PropertyMetadata(null, ResourceKeyChanged));
    static void ResourceKeyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (!(d is FrameworkElement target) || !(e.NewValue is Tuple<object, DependencyProperty> newVal)) return;
        var dp = newVal.Item2;
        if (newVal.Item1 == null)
        {
            target.SetValue(dp, dp.GetMetadata(target).DefaultValue);
            return;
        }
        target.SetResourceReference(dp, newVal.Item1);
    }
    #endregion
    public ResourceBinding() { }
    public ResourceBinding(string path) => Path = new PropertyPath(path);
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if ((IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget)) == null) return null;
        if (((IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget))).TargetObject != null && ((IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget))).TargetObject.GetType().FullName is "System.Windows.SharedDp") return this;
        if (!(((IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget))).TargetObject is FrameworkElement targetObject) || !(((IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget))).TargetProperty is DependencyProperty targetProperty)) return null;
        #region binding
        Binding binding = new Binding
        {
            Path = Path,
            XPath = XPath,
            Mode = Mode,
            UpdateSourceTrigger = UpdateSourceTrigger,
            Converter = Converter,
            ConverterParameter = ConverterParameter,
            ConverterCulture = ConverterCulture,
            FallbackValue = FallbackValue
        };
        if (RelativeSource != null)
            binding.RelativeSource = RelativeSource;
        if (ElementName != null)
            binding.ElementName = ElementName;
        if (Source != null)
            binding.Source = Source;
        #endregion
        var multiBinding = new MultiBinding
        {
            Converter = HelperConverter.Current,
            ConverterParameter = targetProperty
        };
        multiBinding.Bindings.Add(binding);
        multiBinding.NotifyOnSourceUpdated = true;
        targetObject.SetBinding(ResourceBindingKeyHelperProperty, multiBinding);
        return null;
    }
    #region Binding Members
    /// <summary>
    /// The source path (for CLR bindings).
    /// </summary>
    public object Source { get; set; }
    /// <summary>
    /// The source path (for CLR bindings).
    /// </summary>
    public PropertyPath Path { get; set; }
    /// <summary>
    /// The XPath path (for XML bindings).
    /// </summary>
    [DefaultValue(null)]
    public string XPath { get; set; }
    /// <summary>
    /// Binding mode
    /// </summary>
    [DefaultValue(BindingMode.Default)]
    public BindingMode Mode { get; set; }
    /// <summary>
    /// Update type
    /// </summary>
    [DefaultValue(UpdateSourceTrigger.Default)]
    public UpdateSourceTrigger UpdateSourceTrigger { get; set; }
    /// <summary>
    /// The Converter to apply
    /// </summary>
    [DefaultValue(null)]
    public IValueConverter Converter { get; set; }
    /// <summary>
    /// The parameter to pass to converter.
    /// </summary>
    /// <value></value>
    [DefaultValue(null)]
    public object ConverterParameter { get; set; }
    /// <summary>
    /// Culture in which to evaluate the converter
    /// </summary>
    [DefaultValue(null)]
    [TypeConverter(typeof(System.Windows.CultureInfoIetfLanguageTagConverter))]
    public CultureInfo ConverterCulture { get; set; }
    /// <summary>
    /// Description of the object to use as the source, relative to the target element.
    /// </summary>
    [DefaultValue(null)]
    public RelativeSource RelativeSource { get; set; }
    /// <summary>
    /// Name of the element to use as the source
    /// </summary>
    [DefaultValue(null)]
    public string ElementName { get; set; }
    #endregion
    #region BindingBase Members
    /// <summary>
    /// Value to use when source cannot provide a value
    /// </summary>
    /// <remarks>
    /// Initialized to DependencyProperty.UnsetValue; if FallbackValue is not set, BindingExpression
    /// will return target property's default when Binding cannot get a real value.
    /// </remarks>
    public object FallbackValue { get; set; }
    #endregion
    #region Nested types
    private class HelperConverter : IMultiValueConverter
    {
        public static readonly HelperConverter Current = new HelperConverter();
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            return Tuple.Create(values[0], (DependencyProperty)parameter);
        }
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    #endregion
}

實(shí)現(xiàn)效果

到此這篇關(guān)于WPF應(yīng)用程序本地化的最佳方法分享的文章就介紹到這了,更多相關(guān)WPF本地化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • WPF實(shí)現(xiàn)播放RTSP視頻流

    WPF實(shí)現(xiàn)播放RTSP視頻流

    這篇文章主要為大家詳細(xì)介紹了WPF實(shí)現(xiàn)播放RTSP視頻流的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-01-01
  • C#/.net程序調(diào)用Python的教程分享

    C#/.net程序調(diào)用Python的教程分享

    C#的優(yōu)勢(shì)在于window下的開發(fā),不僅功能強(qiáng)大而且開發(fā)周期短。而python則有眾多的第三方庫(kù),可以避免自己造輪子,利用C#來(lái)做界面,而具體實(shí)現(xiàn)使用python來(lái)實(shí)現(xiàn)可以大大提高開發(fā)效率。本文介紹如何使用pythonnet來(lái)執(zhí)行python腳本,希望對(duì)大家有所幫助
    2023-03-03
  • C#中using的使用方式詳解

    C#中using的使用方式詳解

    這篇文章主要介紹了C#中using的使用方式方式詳解,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • C#中的Task.WhenAll和Task.WhenAny方法介紹

    C#中的Task.WhenAll和Task.WhenAny方法介紹

    這篇文章介紹了C#中的Task.WhenAll和Task.WhenAny方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • C#使用FileStream循環(huán)讀取大文件數(shù)據(jù)的方法示例

    C#使用FileStream循環(huán)讀取大文件數(shù)據(jù)的方法示例

    這篇文章主要介紹了C#使用FileStream循環(huán)讀取大文件數(shù)據(jù)的方法,結(jié)合實(shí)例形式分析了FileStream文件流的形式循環(huán)讀取大文件的相關(guān)操作技巧,需要的朋友可以參考下
    2017-05-05
  • C#實(shí)現(xiàn)JWT無(wú)狀態(tài)驗(yàn)證的實(shí)戰(zhàn)應(yīng)用解析

    C#實(shí)現(xiàn)JWT無(wú)狀態(tài)驗(yàn)證的實(shí)戰(zhàn)應(yīng)用解析

    這篇文章主要介紹了C#實(shí)現(xiàn)JWT無(wú)狀態(tài)驗(yàn)證的實(shí)戰(zhàn)應(yīng)用解析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • C#實(shí)現(xiàn)軟件開機(jī)自啟動(dòng)功能(不需要管理員權(quán)限)

    C#實(shí)現(xiàn)軟件開機(jī)自啟動(dòng)功能(不需要管理員權(quán)限)

    在本文中,我們探討了如何使用C#語(yǔ)言實(shí)現(xiàn)應(yīng)用程序在系統(tǒng)啟動(dòng)時(shí)自動(dòng)運(yùn)行的功能,同時(shí)避免了對(duì)管理員權(quán)限的需求,文章通過(guò)代碼示例講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2025-04-04
  • C# newtonsoft.json中文亂碼問(wèn)號(hào)的解決方案

    C# newtonsoft.json中文亂碼問(wèn)號(hào)的解決方案

    這篇文章主要介紹了C# newtonsoft.json中文亂碼問(wèn)號(hào)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • C#簡(jiǎn)單訪問(wèn)SQLite數(shù)據(jù)庫(kù)的方法(安裝,連接,查詢等)

    C#簡(jiǎn)單訪問(wèn)SQLite數(shù)據(jù)庫(kù)的方法(安裝,連接,查詢等)

    這篇文章主要介紹了C#簡(jiǎn)單訪問(wèn)SQLite數(shù)據(jù)庫(kù)的方法,涉及SQLite數(shù)據(jù)庫(kù)的下載、安裝及使用C#連接、查詢SQLIte數(shù)據(jù)庫(kù)的相關(guān)技巧,需要的朋友可以參考下
    2016-07-07
  • 將數(shù)組中指定數(shù)量的元素移動(dòng)數(shù)組后面的實(shí)現(xiàn)代碼

    將數(shù)組中指定數(shù)量的元素移動(dòng)數(shù)組后面的實(shí)現(xiàn)代碼

    本篇文章是對(duì)將數(shù)組中指定數(shù)量的元素移動(dòng)數(shù)組后面的實(shí)現(xiàn)代碼進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06

最新評(píng)論