6

I want to know if there exists a way to set a control's Text property from a resource file in design time:

Set Property

Or this process can only be performed programatically?

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
InfZero
  • 2,944
  • 4
  • 24
  • 36
  • Do you want to set the text property using a `.Resx` file that you made yourself or your actual requirement is localization? – Reza Aghaei Nov 27 '15 at 00:25
  • The first one, @RezaAghaei. – InfZero Nov 27 '15 at 00:26
  • I know to do that programmatically, but I don't how to set the control's `Text` property in design time. – InfZero Nov 27 '15 at 00:27
  • 1
    The designer only serializes string for that property. You can not set the `Text` property to a resource value directly using designer, but you can somehow use an extender to set the resource key for your control at design-time and then use it at run-time. But in general I think using standard Localization mechanisms of windows forms is a better option. – Reza Aghaei Nov 27 '15 at 00:33

1 Answers1

6

The designer only serializes string for Text property. You can not set the Text property to a resource value directly using designer.

Even if you open the Form1.Designer.cs file and add a line to initialization to set the Text property to a resource value like Resource1.Key1, after first change in designer, the designer replace your code by setting the string value of that resource for Text property.

In general I recommend using standard localization mechanisms of windows forms, using Localizable and Language property of Form.

But if in some reason you want to use your resource file and want to use a designer-based solution, as good option you can create an extender component to set the resource key for your control at design-time and then use it at run-time.

Code for the extender component is at the end of the post.

Usage

Make sure you have a resource file. For example Resources.resx in the properties folder. Also make sure you have some resource key/value in the resource file. For example Key1 with value = "Value1", Key2 with value = "Value2". Then:

  1. Put a ControlTextExtender component on your form.
  2. Using property grid set the ResourceClassName property of it to the full name of your resource file for example WindowsApplication1.Properties.Resources` enter image description here
  3. Select each control you want to set its Text and using property grid set the value of ResourceKey on controlTextExtender1 property to the resource key that you want. enter image description here

Then run the application and see the result.

Result

and here is an screenshot of result, and as you see, I even localized Text property of the form this way.

enter image description here

enter image description here

Switch between Cultures at Run-Time

You can switch between cultures at run-time, without need to close and reopen the form simply using:

System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fa");
this.controlTextExtender1.EndInit();

Implementation

Here is a basic implementation of the idea:

[ProvideProperty("ResourceKey", typeof(Control))]
public class ControlTextExtender 
    : Component, System.ComponentModel.IExtenderProvider, ISupportInitialize
{
    private Hashtable Controls;
    public ControlTextExtender() : base() { Controls = new Hashtable(); }

    [Description("Full name of resource class, like YourAppNamespace.Resource1")]
    public string ResourceClassName { get; set; }

    public bool CanExtend(object extendee)
    {
        if (extendee is Control)
            return true;
        return false;
    }

    public string GetResourceKey(Control control)
    {
        return Controls[control] as string;
    }

    public void SetResourceKey(Control control, string key)
    {
        if (string.IsNullOrEmpty(key))
            Controls.Remove(control);
        else
            Controls[control] = key;
    }

    public void BeginInit() { }

    public void EndInit()
    {
        if (DesignMode)
            return;

        var resourceManage = new ResourceManager(this.ResourceClassName, 
                                                 this.GetType().Assembly);
        foreach (Control control in Controls.Keys)
        {
            string value = resourceManage.GetString(Controls[control] as string);
            control.Text = value;
        }
    }
}
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • This works for controls, but not toolstrip items, datagridview columns and controls embedded in other controls, how do i fix this? – Smith Jul 11 '17 at 17:04
  • @Smith If you take a look at the logic of code, you will see that we just provide `ResourceKey` property for `Control` objects. That's because we are going to set `Text` property for them. But if we decide to also extend `Component` classes like `ToolTip`, which have different base class than `Control`, we can not rely on existence of `Text` property. For `DataGridViewColumn` types, as far as I know, you can not create an extender component which work also in column collection editor. – Reza Aghaei Jul 13 '17 at 07:44