4

Before I begin, it seems a similar/same question might have been asked before here, however no definitive answer exists.


Suppose I have a custom winforms control which overrides the Text property:

public class MyControl : Control
{
    [DefaultValue("")]
    public override string Text
    {
        get { return base.Text; }
        set 
        {
            base.Text = value;
            ...
        }
    }

    public MyControl()
    {
        this.Text = "";
    }
}

My question is, How do I prevent the designer from automatically assigning the Text property?

When instances of MyControl are created, the designer automatically assigns the Text property to the name of the control instance, e.g., "MyControl1", "MyControl2", etc. Ideally, I would like the text property to be set to its default, an empty string.

Community
  • 1
  • 1
Lemonseed
  • 1,644
  • 1
  • 15
  • 29
  • try making text property as private. – venkat Mar 04 '16 at 08:03
  • I still need to use the property, and would like to be able to use it from the designer; I could set serialization visibility to false, however I would lose design-time ability to set the property. – Lemonseed Mar 04 '16 at 08:13
  • Have you tried to return `string.Empty`? It looks like that: `public override string Text { get { return string.Empty; } .set ..... }` – StepUp Mar 04 '16 at 08:18
  • 1
    That would accomplish getting the property to be an empty string at design-time; however, I could not set it to anything else from the designer. I want the property to be an empty string by default (not serialized), but still be able to set the property in the designer and have it get serialized. – Lemonseed Mar 04 '16 at 08:21
  • 2
    The proposed option in the linked question doesn't help you because the developer may want to set the `Text` property at design-time. The designer sets `Text` property in `InitializeNewComponent` method. You can create a new designer for your control and override that method and after calling base method, set the `Text` property to empty string. – Reza Aghaei Mar 04 '16 at 09:15
  • Have you looked at how others are solving this? For example, the `TextBox` control doesn't have this behaviour, you can learn from that. – Luaan Mar 04 '16 at 09:28
  • @Luaan great offer! The `TextBoxBaseDesigner` also overrides `InitializeNewComponent` the same way. I looked into `ControlDesigner` and used the criteria from there but looking in `TextBoxBaseDesigner` made me sure about the solution. Also there are more lesson to learn from that designer! – Reza Aghaei Mar 04 '16 at 10:06
  • The expectation of the default designer is that this is helpful, it assumes you'll render the Text property value in your OnPaint() method and that the user will change it after he dropped it on the form. Makes the control easier to find back. You could create your own designer but it sure sounds like you always want to start with an empty string at runtime. Add the [Browsable(false)] attribute. – Hans Passant Mar 04 '16 at 10:25
  • 2
    Creating a custom designer makes control start with an empty `Text` at design-time. Also the developer can change the value using property grid at design-time. If you set `[Browsable(false)]` on `Text` property, then the user can not change the property at design-time. – Reza Aghaei Mar 04 '16 at 11:23

1 Answers1

4

The designer sets Text property of control in InitializeNewComponent of ControlDesigner.
You can create a new designer for your control and override that method and after calling base method, set the Text property to empty string.

This way your control starts with an empty Text property and also you can change the value of Text using property grid at design-time.

using System.ComponentModel;
using System.Windows.Forms;
using System.Windows.Forms.Design;

[Designer(typeof(MyControlDesigner))]
public partial class MyControl: Control
{
}

public class MyControlDesigner : ControlDesigner
{
    public override void InitializeNewComponent(System.Collections.IDictionary defaultValues)
    {
        base.InitializeNewComponent(defaultValues);

        PropertyDescriptor descriptor = TypeDescriptor.GetProperties(base.Component)["Text"];
        if (((descriptor != null) && (descriptor.PropertyType == typeof(string))) && (!descriptor.IsReadOnly && descriptor.IsBrowsable))
        {
            descriptor.SetValue(base.Component, string.Empty);
        }
    }
}
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • I just copied your ControlDesigner and put it on my custom textbox control that inherits from the `Control` class. But, when I drag my custom control from the *ToolBox* and put it in my form, I get: `Value must be of type 'System.Web.UI.Control'. Parameter name: component` How do I fix that? – Beyondo May 24 '19 at 22:05
  • Okay, nevermind... It worked now for some reason! And I also needed to add `[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]` for the `Text` property because it wasn't serializing when I added the custom designer. – Beyondo May 24 '19 at 23:45
  • 1
    @XStylish `System.Web.UI.Control` means you are using a wrong namespace. The correct one should be `System.Windows.Forms.XXXX`. – Reza Aghaei May 25 '19 at 04:03
  • Ohh, so that's why! I copied your ControlDesigner only without the namespaces in your code and so I let Visual Studio generate these namespaces for me but it generated the wrong ones; Thanks for letting me know because I may encounter that problem again someday so I wouldn't know how to fix it without you. :) – Beyondo May 25 '19 at 11:28
  • +1. You're the MAN sir. Your answers have taught me a lot about design time behavior of custom controls. – Xam Jul 19 '19 at 05:47