Changing CurrentUICulture at runtime in a Localizable Form in WinForms

后端 未结 3 2042
囚心锁ツ
囚心锁ツ 2020-12-12 03:26

I have been searching about how to change the language of a Form that has the Localizable attribute set to true.

https://msdn.microsoft.com/en-us/librar

3条回答
  •  失恋的感觉
    2020-12-12 03:52

    MVVM (Model - View - ViewModel) approach have some benefits which can be useful in your case.

    Create new resource files for languages which you will use for localization. Working with form's own resource files can be little bid tricky because it regenerated every time you make change in the designer - so I think own resource file will be easier to maintain and even share with other forms and even projects.

    LocalizationValues.resx // (default english), set Access Modifier to "Internal" or "Public"
        "Title": "Title"
        "Description": "Description"
    
    LocalizationValues.es.resx
        "Title": "Título"
        "Description": "Descripción"
    

    Visual Studio generate static class LocalizationValues with properties as keys of .resx file. So "Title" can be accessed as LocalizationValues.Title

    Create "viewmodel" class which represents all texts you are using in localization. Class should implements INotifyPropertyChanged interface.

    public class LocalizationViewModel : INotifyPropertyChanged
    {
        public string Title
        {
            get
            {
                return LocalizationValues.Title;
            }
        }
    
        public string Description
        {
            get
            {
                return LocalizationValues.Description;
            }
        }
    
        public void SetLanguage(string language)
        {
            var culture = new CultureInfo(language);
            Thread.CurrentThread.CurrentUICulture = culture;
    
            // This is important, 
            // By raising PropertyChanged you notify Form to update bounded controls
            NotifyAllPropertyChanged();
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected void NotifyAllPropertyChanged()
        {
            // Passing empty string as propertyName
            // will indicate that all properties of viewmodel have changed
            NotifyPropertyChanged(string.Empty);
        }
    
        protected void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    

    Then in Form bind viewmodel to controls

    public partial class YourForm : Form
    {
        private LocalizationViewModel _viewmodel;
    
        public YourForm()
        {
            InitializeComponent();
    
            _viewmodel = new LocalizationViewModel();
    
            // Bound controls to correspondent viewmodel's properties
            LblTitle.DataBindings.Add("Text", _viewmodel, "Title", true);
            LblDescription.DataBindings.Add("Text", _viewmodel, "Description", true);
        }
    
        // Menu buttons to change language
        private void SpanishToolStripMenuItem_Click(object sender, EventArgs e)
        {
            _viewmodel.SetLanguage("es");
        }
    
        private void EnglishToolStripMenuItem_Click(object sender, EventArgs e)
        {
            _viewmodel.SetLanguage("en");
        }
    }
    

    Approach above will provide more benefits then only updating controls. You get clearly separated parts of your application, which can be tested independently from each other.

提交回复
热议问题