1
votes

Using C# and WinForms, I can set a form to be localizable, put a label on it, and set text for the label in as many languages as I want. The text will be stored as string resources in one resource file for each language. Then, a user can select a language and all labels on the form will change to the correct language.

This does not seem to work for combo boxes. I can add items to a combo box for a localizable form and they will be stored in resource files using names such as ComboBox1.Item, ComboBox1.Item1, and ComboBox1.Item2, but the displayed text does not change when the combo box changes.

I've seen various suggestions for how to localize combo boxes, based on binding them to dictionaries or lists of tuples, but it seems to me that if items are stored in resource strings, there should be some more automatic way to use those resource strings. Is there?

Edit: Here is what should be a minimal example. A form has a text box, a button, a label and a combo box. The label and combo box each have resources for French (fr-FR) and Spanish (es-ES). The language name is entered in the text box, and the button changes the form's language using the following method:

private void ChangeLanguage(string lang)
{
    ComponentResourceManager crm = new ComponentResourceManager(typeof(Form2));
    CultureInfo culture = CultureInfo.CreateSpecificCulture(lang);
    Thread.CurrentThread.CurrentCulture = culture;
    Thread.CurrentThread.CurrentUICulture = culture;

    foreach (Control c in this.Controls)
    {
        crm.ApplyResources(c, c.Name, culture);
    }

}

The result is that the label's text changes but the text of the combo box items does not.

1
ComboBox.Items is localizable by default. What's the problem?Reza Aghaei
I have labels and combo boxes on my little sample form. When I change the language of the form, the labels change language but the combo box items don't.ROBERT RICHARDSON
In a minimal reproducible example it works properly for me. Create a MCVE and try it yourself.Reza Aghaei

1 Answers

1
votes

If you close and reopen the form, everything will work fine. But if you would like to change the culture without closing the form, you need to add extra processing for ComboBox:

if (c is ComboBox)
{
    var combo = (ComboBox)c;
    var count = combo.Items.Count;
    combo.Items.Clear();
    combo.BeginUpdate();
    for (int i = 0; i < count; i++)
    {
        var number = i == 0 ? "" : $"{i}";
        var item = crm.GetString($"{c.Name}.Items{number}");
        combo.Items.Add(item);
    }
    combo.EndUpdate();
}
crm.ApplyResources(c, c.Name);

Also keep in mind that your function is just applying the resource on the controls on the form and it's ignoring nested controls. For example, if some controls are hosted on a panel, it will ignore them. To fix this issue, take a look at this post.

Note:

In general , I recommend restarting the form to apply new language, because the custom logic is not limited to ComboBox, you need specific logic for ComboBox, ListBox, ListView, TreeView, DataGridView, ToolStrip, ContextMenuStrip, MenuStrip, StatusStrip and maybe smoe other controls which I forget to mention.

In short, I believe saving the selected culture in a setting and then Application.Restart() and applying culture in Main method is what you are looking for.