1

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.

The rigjh
  • 67
  • 1
  • 7
  • Please share a [mcve]. – mjwills Oct 30 '20 at 04:15
  • 1
    I can't get this code working to really see what the problem is. But generally, a TextBox requires more room than a label to display correctly. So have you tried sizing the label to be larger? To see if this is OK (both height and width, remember to disable autosizing). – jason.kaisersmith Oct 30 '20 at 05:08
  • 1
    Would it not be simpler to just have a textbox and restyle it into being "like a label" ? Set read only and remove the border? I believe it's what Microsoft do in a file properties dialog so e.g. the path looks like a label but can be copied – Caius Jard Oct 30 '20 at 05:44
  • But the textbox would now look opaque. – The rigjh Oct 30 '20 at 13:24

1 Answers1

1

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.
dr.null
  • 4,032
  • 3
  • 9
  • 12