Search code examples
c#textboxuser-controlswindows-forms-designer

Why is the size of the TextBox cut off?


I wrote a small control that allows to change from label to text box and vice versa, and everything is fine, the problem is that it cuts when going from label to text box, which is strange because while I was testing it everything worked perfectly.

https://i.imgur.com/yo2tz9O.gif

using System;
using System.Windows.Forms;

namespace LabelBox
{
    public partial class labelbox : Label
    {
        public TextBox textBox = new TextBox();

        public labelbox()
        {
            InitializeComponent();

            textBox.LostFocus += TextBox_LostFocus;
            textBox.KeyDown += TextBox_KeyDown;
            this.Controls.Add(textBox);
            textBox.Hide();
            textBox.Visible = false;
            this.AutoSize = false;
        }

        

        // Sobrescribir el metodo Double Click de la clase Label
        protected override void OnDoubleClick(EventArgs e)
        {
            textBox.Show();
            textBox.Visible = true;
            textBox.Text = this.Text;
            textBox.Focus();
        }

        // Agreagar el metodo Lost Focus del textbox
        protected void TextBox_LostFocus(object sender, EventArgs e)
        {
            this.Text = textBox.Text;
            textBox.Hide();
            textBox.Visible = false;
        }

        // Agregar el metodo Key Down para ENTER del textbox
        private void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if(e.KeyCode == Keys.Enter)
            {
                this.Text = textBox.Text;
                textBox.Hide();
                textBox.Visible = false;
            }
        }                        

    }
}

I even tried modifying the size of the text box to be the same as the label.


Solution

  • Setting this.AutoSize = false; in the constructor doesn't disable the property and the auto sizing remains. The type of the ToolBoxItem attribute of the Label control (as the CheckBox and the RadioButton) is AutoSizeToolboxItem which enables the AutoSize property when you drop an instance in the designer. This issue is well explained here.

    As the referred answer suggests, you can prevent this behavior by decorating the class with the [ToolboxItem(typeof(ToolboxItem))] attribute:

    using System.Drawing;
    using System.Drawing.Design;
    using System.Windows.Forms;
    using System.ComponentModel;
    
    [ToolboxItem(typeof(ToolboxItem))]
    public partial class LabelBox : Label
    {
        //...
    }
    

    Alternatively, override the AutoSize property to always return false:

    public partial class LabelBox : Label
    {
        [Browsable(false),
            Bindable(false),
            DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
            EditorBrowsable(EditorBrowsableState.Never)]
        public override bool AutoSize => false;
    }
    

    Implemented here for the CheckBox control thanks to the comments.

    Suggestion: You could rewrite your custom control as follows:

    [ToolboxItem(typeof(ToolboxItem))]
    public class LabelBox : Label
    {
        public LabelBox() : base() { }
    
        // To be able to set the properties of the TextBox in the Properties Window.
        [Browsable(true),
            DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public TextBox TextBox { get; } = new TextBox();
    
        protected override void OnHandleCreated(EventArgs e)
        {
            if (!Controls.Contains(TextBox))
            {
                TextBox.Leave += (s, a) =>
                {
                    Text = TextBox.Text;
                    TextBox.Hide();
                };
                TextBox.KeyDown += (s, a) =>
                {
                    if (a.KeyCode == Keys.Enter)
                    {
                        Text = TextBox.Text;
                        TextBox.Hide();
                        // Optional to prevent the beep...
                        a.SuppressKeyPress = true;
                    }
                };
                TextBox.Visible = false;
                TextBox.Dock = DockStyle.Fill;
                Controls.Add(TextBox);
            }
    
            base.OnHandleCreated(e);
        }
    
        protected override void OnDoubleClick(EventArgs e)
        {
            TextBox.Show();
            TextBox.Text = Text;
            TextBox.Focus();
        }
    
        // When you create a disposable object, then you should dispose it.
        protected override void Dispose(bool disposing)
        {
            if (disposing) TextBox.Dispose();
            base.Dispose(disposing);
        }
    }
    

    Side Notes:

    1. Calling the InitializeComponent(); method in this context makes no sense.
    2. To toggle the visibility state of a control, use the Visible property Or the Show/Hide methods but not both to do the same thing.