Creating a Windows Forms Label that wraps with C#

One of the few annoyances I occasionally get with C# is the lack of a word wrap facility for the standard Label control.

Instead, if the AutoSize property is set to True, the label will just get wider and wider. In order to wrap it, you have to disable auto resize then manually ensure the height of the label is sufficient.

The base Control class has method named GetPreferredSize which is overridden by derived classes. This method will calculate the size of a control based on a suggested value. By calling this method and overriding the OnTextChanged and OnResize methods, we can very easily create a custom label that automatically wraps and resizes itself vertically to fit its contents.

Paste in the following code into a new Component to have a read-to-run wrappable label.

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace Cyotek.Windows.Forms
{
  public partial class WrapLabel : Label
  {
		#region  Public Constructors  

    public WrapLabel()
    {
      this.AutoSize = false;
    }

		#endregion  Public Constructors  

		#region  Protected Overridden Methods  

    protected override void OnResize(EventArgs e)
    {
      base.OnResize(e);

      this.FitToContents();
    }

    protected override void OnTextChanged(EventArgs e)
    {
      base.OnTextChanged(e);

      this.FitToContents();
    }

		#endregion  Protected Overridden Methods  

		#region  Protected Virtual Methods  

    protected virtual void FitToContents()
    {
      Size size;

      size = this.GetPreferredSize(new Size(this.Width, 0));

      this.Height = size.Height;
    }

		#endregion  Protected Virtual Methods  

		#region  Public Properties  

    [DefaultValue(false), Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public override bool AutoSize
    {
      get { return base.AutoSize; }
      set { base.AutoSize = value; }
    }

		#endregion  Public Properties  
  }
}

So, what is the code doing? It's very straightforward.

In the constructor, we are disabling the built in auto resize functionality, otherwise you won't be able to resize the control in the designer.

Next, we want to overide the OnTextChanged and OnResize methods to call our new resize functionality. By overriding these, we can ensure that the control will correctly resize as required.

Now to implement the actual resize functionality. The FitToContents method calls the label's GetPreferredSize method, passing in the width of the control. This method returns a Size structure which is large enough to hold the entire contents of the control. We take the Height of this (but not the width) and apply it to the label to make it resize vertically.

When calling GetPreferredSize, the size we passed in only had the width specified, which will be the maximum width returning. As we passed in zero for the height, the method defines its own maximum height.

Finally, you'll note that we have overridden the AutoSize property itself and added a number of attributes to it to make sure it doesn't appear in any property or code windows, and to prevent its value from being serialized.

About The Author

Gravatar

The founder of Cyotek, Richard enjoys creating new blog content for the site. Much more though, he likes to develop programs, and can often found writing reams of code. A long term gamer, he has aspirations in one day creating an epic video game. Until that time, he is mostly content with adding new bugs to WebCopy and the other Cyotek products.

Leave a Comment

While we appreciate comments from our users, please follow our posting guidelines. Have you tried the Cyotek Forums for support from Cyotek and the community?

Styling with Markdown is supported

Comments

Aaron

# Reply

Thanks, looking for this.

You do know "this." is optional, right?

Gravatar

Richard Moss

# Reply

Aaron,

Yes, of course "this" is optional. However, and especially when mixing with "base", I like to be explicit, then the reader should have no difficulty in understanding my meaning. Sometimes I forget though :)

Regards;

[Now I wish we'd built a "reply" functionality into this comment system]

Gravatar

Jim

# Reply

This is exactly what I was looking for. And it works, too. Thanks for the post!

BTW - I completely agree with using 'this' and 'base'. Readability is definitely improved.

Exorsus

# Reply

Whatever you do, there is always someone who tells you ... you are an idiot ... for example some people are using automatic code cleanup using tools like ReSharper and StyleCop so adding base and they can use this explicitly.