Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I implement an AutoSize property to a Custom Control?

I want to implement an AutoSize property in a Custom Control (not User Control), in such a way that it behaves like other standard .NET WinForms controls which implement AutoSize (ala CheckBox) in design mode.

I have the property set up, but it's the way the control behaves in design mode that bugs me. it can still be resized, which doesn't make sense because the visual resize isn't reflected in the AutoSize and Size properties i've implemented.

Standard .NET controls do not allow resizing (or even show resize handles) in design mode when AutoSize is true. I want my control to behave in the same fashion.

Edit: I have it working using the SetBoundsCore() override, but it doesn't visually restrict a resize when AutoSize is set to true, it just has the same effect; the functionality is equivalent, but it feels unnatural.

protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
{
    if (!this.auto_size)
        this.size = new Size(width, height);
    base.SetBoundsCore(x, y, this.size.Width, this.size.Height, specified);
}

Any ideas on doing this the standard way?

like image 878
mina Avatar asked Mar 25 '12 00:03

mina


1 Answers

Here's my recipe to have your control AutoSize.

Create a method GetAutoSize() to calculate the required size of the control according to your specific implementation. Maybe it's the size of the text it contains or the total height of the controls for the current width, whatever.

Create a method ResizeForAutoSize() to force the control to resize itself following a change in its state. For example if the control is sized for the text it contains, changing the text should have the control resized. Just call this method when the text changes.

Override GetPreferredSize() to notify whoever wants to know (like a FlowLayoutPanel for instance) what is our preferred size.

Override SetBoundsCore() to enforce our sizing rule the same way an AutoSize label cannot be resized.

See sample here.

/// <summary>
/// Method that forces the control to resize itself when in AutoSize following
/// a change in its state that affect the size.
/// </summary>
private void ResizeForAutoSize()
{
    if( this.AutoSize )
        this.SetBoundsCore( this.Left, this.Top, this.Width, this.Height,
                    BoundsSpecified.Size );
}

/// <summary>
/// Calculate the required size of the control if in AutoSize.
/// </summary>
/// <returns>Size.</returns>
private Size GetAutoSize()
{
    //  Do your specific calculation here...
    Size size = new Size( 100, 20 );

    return size;
}

/// <summary>
/// Retrieves the size of a rectangular area into which
/// a control can be fitted.
/// </summary>
public override Size GetPreferredSize( Size proposedSize )
{
    return GetAutoSize();
}

/// <summary>
/// Performs the work of setting the specified bounds of this control.
/// </summary>
protected override void SetBoundsCore( int x, int y, int width, int height,
        BoundsSpecified specified )
{
    //  Only when the size is affected...
    if( this.AutoSize && ( specified & BoundsSpecified.Size ) != 0 )
    {
        Size size = GetAutoSize();

        width   = size.Width;
        height  = size.Height;
    }

    base.SetBoundsCore( x, y, width, height, specified );
}
like image 54
ML64 Avatar answered Sep 22 '22 10:09

ML64