资源文件中的WinForms字符串,在设计器中连接

我正在尝试为多种语言本地化WinForms应用程序。 我试图找到一种方法来设置我的表单标签/按钮文本属性,以从设计器中的资源文件中读取(而不是必须维护一个以编程方式设置它们的代码块)。

我发现我可以设置form.Localizable = true,但是然后从表单旁边的文件中读取资源,但是我的许多资源在多个表单中共享。

有没有办法在设计器中将标签的文本设置为存储在项目级resx文件中的值?

要回答这个问题,不。

但IMO,如果文本是静态的,不应该这样做。

阅读我对本地化和资源的回答:
资源字符串位置
全球化现有的Windows窗体应用程序
将.resx文件用于全局应用程序消息

我想我找到了办法做到这一点!

首先在Resources.resx中将Access Modifier设置为Public。

之后在设计器生成的代码(Form.Designer.cs)中,您可以将其写入适当的控件:

this..Text = Properties.Resources. 

例如:

 this.footerLabel.Text = Properties.Resources.footerString; 

ps.:我不知道这个解决方案有多道德,但它有效!

我能想到的唯一方法是创建一个为资源名称添加属性的自定义控件。 设置属性后,从项目资源文件中获取值并使用它设置text属性。 您需要确保Text不会被序列化,或者它可能会覆盖ResourceName设置的值。

 public class ResourceLabel : Label { private string mResourceName; public string ResourceName { get { return mResourceName; } set { mResourceName = value; if (!string.IsNullOrEmpty(mResourceName)) base.Text = Properties.Resources.ResourceManager.GetString(mResourceName); } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public override string Text { get { return base.Text; } set { // Set is done by resource name. } } } 

顺便说一句,这很容易实现,可以为您想要绑定到资源或任何其他类的任何类型的控件执行此操作。 我这样做也适用于静态类,比如我的应用程序设置。

输入这样的代码:

 textBox2.DataBindings.Add("Text", source, "."); 

没有给我一个“好感觉”,更别提拼写了

以下是上述标签的小样本,它提供了应用程序资源的下拉列表。

首先是控件,包含1个名为ResourceName的新属性,魔术来自编辑器,这个属性在属性上方的注释中指定,称为ResourceDropDownListPropertyEditor

 [Editor(typeof(ResourceDropDownListPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))] 

标签类的代码:

 ///  /// Label bound to resource ///  ///  /// The bitmap does not appear in the Toolbox for autogenerated controls and components. /// https://docs.microsoft.com/en-us/dotnet/framework/winforms/controls/how-to-provide-a-toolbox-bitmap-for-a-control ///  [ToolboxBitmap(typeof(Label))] public partial class ResourceLabel : Label { ///  /// backing field for the resource key property ///  private string mResourceName; [Browsable(true)] [DefaultValue("")] [SettingsBindable(true)] [Editor(typeof(ResourceDropDownListPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [Description("Select the resource key that you would like to bind the text to.")] public string ResourceName { get { return mResourceName; } set { mResourceName = value; if (!string.IsNullOrEmpty(mResourceName)) { base.Text = Properties.Resources.ResourceManager.GetString(mResourceName); } } } ///  /// Designer helper method: https://msdn.microsoft.com/en-us/library/ms973818.aspx ///  /// true if XXXX, false otherwise. private bool ShouldSerializeResourceName() { return !string.IsNullOrEmpty(ResourceName); } ///  /// Will be default text if no resource is available ///  [Description("default text if no resource is assigned or key is available in the runtime language")] public override string Text { get { return base.Text; } set { // Set is done by resource name. } } } 

以下是用于下拉列表的类:

 ///  /// used for editor definition on those properties that should be able /// to select a resource ///  ///  class ResourceDropDownListPropertyEditor : UITypeEditor { IWindowsFormsEditorService _service; ///  /// Gets the editing style of the  method. ///  /// An ITypeDescriptorContext that can be used to gain additional context information. /// Returns the DropDown style, since this editor uses a drop down list. public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { // We're using a drop down style UITypeEditor. return UITypeEditorEditStyle.DropDown; } ///  /// Displays a list of available values for the specified component than sets the value. ///  /// An ITypeDescriptorContext that can be used to gain additional context information. /// A service provider object through which editing services may be obtained. /// An instance of the value being edited. /// The new value of the object. If the value of the object hasn't changed, this method should return the same object it was passed. public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) { if (provider != null) { // This service is in charge of popping our ListBox. _service = ((IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService))); if (_service != null) { var items = typeof(Properties.Resources).GetProperties() .Where(p => p.PropertyType == typeof(string)) .Select(s => s.Name) .OrderBy(o => o); var list = new ListBox(); list.Click += ListBox_Click; foreach (string item in items) { list.Items.Add(item); } if (value != null) { list.SelectedValue = value; } // Drop the list control. _service.DropDownControl(list); if (list.SelectedItem != null && list.SelectedIndices.Count == 1) { list.SelectedItem = list.SelectedItem.ToString(); value = list.SelectedItem.ToString(); } list.Click -= ListBox_Click; } } return value; } private void ListBox_Click(object sender, System.EventArgs e) { if (_service != null) _service.CloseDropDown(); } } 

最后,您将在设计时看到这样的内容: 设计时视图

在表单上删除控件时会创建资源名称,直到您重新编译并关闭/打开表单或在表单上删除新标签后才会看到更改。

快乐的编码

沃尔特