In a WinForms application, a Panel
is used as a placeholder to display a single User Control as a navigation strategy: whenever the user wishes to navigate to a given area, the respective User Control is added to the Panel. Simplified:
contentPanel.Controls.Clear();
userControl.Dock = DockStyle.Fill;
contentPanel.Controls.Add(userControl);
As a result of a requirement that is out of my control, the Form must support switching the language dynamically. This is implemented and working fine using Hans Passant's answer, with a modification to use the User Control's Resource Manager, which correctly gets and applies the localized text to controls.
After applying the resources from the User Control's respective resource file, however, the layout resulting from DockStyle.Fill
is lost for the User Control's constituent controls that are not themselves set to have a DockStyle.Fill
. This has the effect that controls no longer stretch to fill the available area, and are limited to the original size defined in the designer/resource file. Note that the Dock
property of the User Control is still set correctly to DockStyle.Fill
after applying the resources.
I created an example application which illustrates/reproduces the problem: the form below has a panel to which a user control is added dynamically and set to DockStyle.Fill
. The user control has a label which is anchored top left on the Default locale and top right in the German locale. I would expect the form to snap the label which is anchored to the right against the right margin of the form, but the size of the user control is reset to the value at design time. View source code.
If I start the form on the German locale, the label is correctly laid out against the right edge of the form:
What I'd like to happen is that the layout is retained after calling ApplyResources
. Of course I could simply make a copy of the controls' Location
and Size
properties (as suggested in another answer to the same question mentioned above) but unfortunately values of these properties differ between locales. So, after the localized string and positioning are applied, how can the User Control be directed to layout all its controls anew?
What I've tried
- By looking into
InitializeComponent()
, I've tried callingPerformLayout()
to thePanel
container, the User Control, and the Form to no avail. - Adding
SuspendLayout()
andResumeLayout(true)
before and after the call to ApplyResources, also without success.
Additional implementation details
- References to instantiated User Controls are kept in a private dictionary in the Main Form. When navigation for that control is raised, the previous user control is removed and the existing reference added with the snippet above.
Reacting to the user event of changing the language:
protected virtual void OnChangeCulture(CultureInfo newCulture) { System.Threading.Thread.CurrentThread.CurrentCulture = newCulture; System.Threading.Thread.CurrentThread.CurrentUICulture = newCulture; SuspendLayout(); ComponentResourceManager resources = new ComponentResourceManager(this.GetType()); ApplyResources(resources, this, newCulture); ResumeLayout(true); }
Applying the resources to all controls in the form:
private void ApplyResources(ComponentResourceManager resourceMgr, Component target, CultureInfo culture) { //Since target can be a Control or a Component, get their name and children (OMITTED) in order to apply the resources and recurse string name; IEnumerable<Component> children; //Have the resource manager apply the resources to the given target resourceMgr.ApplyResources(target, name, culture); //iterate through the collection of children and recursively apply resources foreach (Component c in children) { //In the case of user controls, they have their own ResourceManager with the translated strings, so get it and use it instead if (c is UserControl) resourceMgr = new ComponentResourceManager(c.GetType()); //recursively apply resources to the child this.ApplyResources(resourceMgr, c, culture); } }
Many thanks in advance for any pointers!
ComponentResourceManager
is loaded and used in the call toApplyResources
– Amyamyas