I have this piece of code which works:
'Calls after changing Thread.CurrentThread.CurrentUICulture
'and Threading.Thread.CurrentThread.CurrentCulture
'MainPagesBaseForm.vb
Imports System.ComponentModel
Protected Overridable Sub ChangeUILang()
Dim t As Type = Me.GetType
Dim resMgr As ComponentResourceManager
While (Not t.Equals(GetType(Form)))
resMgr = New ComponentResourceManager(t)
Try
ChangeUILangWork(Me, resMgr)
Catch ex As Resources.MissingManifestResourceException
'resource file doesn't exist, skip
End Try
t = t.BaseType
End While
End Sub
Private Sub ChangeUILangWork(ctr As Control, resMgr As ComponentResourceManager)
For Each ctrUnit As Control In ctr.Controls
If ctrUnit.Visible Then
'Change Lang for the control
resMgr.ApplyResources(ctrUnit, ctrUnit.Name, _
Thread.CurrentThread.CurrentUICulture)
'override visiblity in designer. Already checked to be visible
ctrUnit.Visible = True
'For image based controls
If (TypeOf ctrUnit Is ImageBaseControlI) Then
DirectCast(ctrUnit, ImageBaseControlI).ChangeLang()
End If
'Recursion
If ctrUnit.HasChildren Then
If TypeOf ctrUnit Is UserControl Then
'Look into its own .resx for user controls
Dim resMgr2 As New ComponentResourceManager(ctrUnit.GetType)
ChangeUILangWork(ctrUnit, resMgr2)
Else
ChangeUILangWork(ctrUnit, resMgr)
End If
'For panels with custom paint
ctrUnit.Invalidate()
End If
End If
Next ctrUnit
End Sub
Is there any proper way to change the UI language at run-time, including user controls and inhered controls, instead of applying all resource files to all elements like this? Shouldn't the controls know where their localization data is?
Is there anyway to check whether a resource file exist? I would like to avoid empty try catch if possible.
Background:
Hi, I have a WinForm application that needs to change its UI Language at run-time. Structure of the forms are as following:
'This defines the layout of the main pages
Public Class MainPageBaseForm
Inherits Form
Protected LblHeader As Label 'Added and localized from designer
'...
End Class
'This defines common event handlers for pages related to books
'No localization file for this class
Public Class BooksBaseForm
Inherits MainPageBaseForm
Event BookStatusChanged(sender As Object, e As BookStatusEventArgs)
'...
End Class
'Individual pages / forms
Public Class FrmBooks001
Inherits BooksBaseForm
Protected LblDesc As Label 'Localized Label added from designer
Protected SearchKeysInputFields As BooksEnqInForm 'Localized user control
Protected BntChLang As Button 'Button to switch UI culture
'Other controls like textboxes & buttons for this page
'...
End Class
When the switch culture button clicked, the Form's Controls
should be refreshed. I have found the way that works for simple forms(How do I change the culture of a WinForms application at runtime):
Private Sub ChangeUILang(parentCtr As Control)
Dim resMgr As New System.ComponentModel.ComponentResourceManager(GetType(FrmBooks001))
For Each ctr As Control In parentCtr.Controls
resources.ApplyResources(ctr, ctr.Name, New CultureInfo("zh"))
if ctr.HasChildren then
ChangeUILang(ctr)
end if
Next
End Sub
However this only works on controls directly defined in FrmBooks001, and only vanilla controls (not UserControl
). I figured the reason from this post:
Switching language (cultureinfo/globalization) does not affect ToolStripMenuItems
you are looking for the localization information in System.Windows.Forms.ToolStripMenuItem.resx file, but you want to look in your Forms resources file.
(The situation here is the opposite which the UserControls has their own .resx files)
So the only solution (I can thought of) is to loop through all resource file of the classes in inheritance tree and the UserControls (and apply all redundantly!). Sorry for the long post, please see the top for what I currently use and the questions. Thanks in advance.