ComboBoxes如何将字符串资源用于项目文本? [英] How can ComboBoxes use string resources for item text?

查看:104
本文介绍了ComboBoxes如何将字符串资源用于项目文本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用C#和WinForms,我可以将表单设置为可本地化的,在其上放置标签,并使用所需的多种语言为标签设置文本.文本将作为字符串资源存储在每种语言的一个资源文件中.然后,用户可以选择一种语言,并且表单上的所有标签都将更改为正确的语言.

这似乎不适用于组合框.我可以将项目添加到组合框以获取可本地化的表单,并且它们将使用诸如ComboBox1.Item,ComboBox1.Item1和ComboBox1.Item2之类的名称存储在资源文件中,但是当组合框更改时,显示的文本不会更改.

基于将组合框绑定到字典或元组列表上,我已经看到了各种有关如何定位组合框的建议,但是在我看来,如果项目存储在资源字符串中,则应该有一些更自动的使用方式这些资源字符串.有吗?

这应该是一个最小的示例.表单具有一个文本框,一个按钮,一个标签和一个组合框.标签和组合框均具有法语(fr-FR)和西班牙语(es-ES)的资源.在文本框中输入语言名称,然后该按钮使用以下方法更改表单的语言:

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);
    }

}

结果是标签的文本发生了变化,但组合框项目的文本没有发生变化.

解决方案

如果关闭并重新打开表单,一切将正常进行.但是,如果您想在不关闭表单的情况下更改区域性,则需要为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);

还请记住,您的函数只是将资源应用于窗体上的控件,而忽略了嵌套控件.例如,如果某些控件托管在面板上,它将忽略它们.要解决此问题,请查看这篇文章.

注意:

通常,我建议重新启动表单以应用新语言,因为自定义逻辑不限于ComboBox,因此您需要ComboBoxListBoxListViewTreeViewDataGridViewToolStripContextMenuStripMenuStripStatusStrip,也许还欺骗了我忘记提及的其他控件.

简而言之,我相信您正在寻找的是将选定的区域性保存到一个设置中,然后将其保存在Application.Restart()中,并以Main方法应用区域性.

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.

解决方案

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.

这篇关于ComboBoxes如何将字符串资源用于项目文本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆