WinForms strings in resource files, wired up in designer
I think I found a way to do this!
First in your Resources.resx set the Access Modifier to Public.
After that in the designer generated code (Form.Designer.cs) you can write this to the appropriate control:
this.<control>.Text = Properties.Resources.<stringname>
for example:
this.footerLabel.Text = Properties.Resources.footerString;
ps.:I don't know how ethical this solution is, but it works!
To answer the question, no.
But IMO, this should not be done anyways if the text will be static.
Have a read at my answers on localization and resources:
Resource string location
Globalize an existing Windows Forms application
Using .resx files for global application messages
Easy enough to implement, by the way, this can be done for any type of control you like to bind to a resource, or any other class. I do this for static classes like my application settings as well.
Entering code like this:
textBox2.DataBindings.Add("Text", source, "<className>.<PropertyName>");
is not giving me a "good feeling", never mind the spelling
Here is a litle sample of the above label that provides a dropdown on the resources of a application.
First the control, contains 1 new property named ResourceName the magic comes from the editor, this one is specified in the annotation above the property and is called ResourceDropDownListPropertyEditor
[Editor(typeof(ResourceDropDownListPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))]
The code for the label class:
/// <summary>
/// Label bound to resource
/// </summary>
/// <remarks>
/// 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</remarks>
/// <seealso cref="System.Windows.Forms.Label" />
[ToolboxBitmap(typeof(Label))]
public partial class ResourceLabel : Label
{
/// <summary>
/// backing field for the resource key property
/// </summary>
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);
}
}
}
/// <summary>
/// Designer helper method: https://msdn.microsoft.com/en-us/library/ms973818.aspx
/// </summary>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
private bool ShouldSerializeResourceName()
{
return !string.IsNullOrEmpty(ResourceName);
}
/// <summary>
/// Will be default text if no resource is available
/// </summary>
[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.
}
}
}
Here is the class used for the drop down:
/// <summary>
/// used for editor definition on those properties that should be able
/// to select a resource
/// </summary>
/// <seealso cref="System.Drawing.Design.UITypeEditor" />
class ResourceDropDownListPropertyEditor : UITypeEditor
{
IWindowsFormsEditorService _service;
/// <summary>
/// Gets the editing style of the <see cref="EditValue"/> method.
/// </summary>
/// <param name="context">An ITypeDescriptorContext that can be used to gain additional context information.</param>
/// <returns>Returns the DropDown style, since this editor uses a drop down list.</returns>
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
// We're using a drop down style UITypeEditor.
return UITypeEditorEditStyle.DropDown;
}
/// <summary>
/// Displays a list of available values for the specified component than sets the value.
/// </summary>
/// <param name="context">An ITypeDescriptorContext that can be used to gain additional context information.</param>
/// <param name="provider">A service provider object through which editing services may be obtained.</param>
/// <param name="value">An instance of the value being edited.</param>
/// <returns>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.</returns>
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();
}
}
In the end what you get will look like this at design-time:
The resource names are created when you drop the control on your form, changes are not seen till you re-compile and close/open the form or drop a new label on the form.