Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Resize Form To Fit DataGridView

5.00/5 (1 vote)
4 Jan 2016CPOL4 min read 34.4K   539  
Attempts to resize a Form to show the entire table of a DataGridView

Introduction

The WinForms DataGridView has a lot of smarts built into it so that it can easily deal with presenting a large grid in a small Form, but many times the developer would prefer to automatically expand the Form in order to show all (or most) of the grid rather than make the user do so manually. Such functionality is not built into the framework, and a quick online search will turn up many developers seeking a solution.

Something the user (and therefore the developer) will likely wish to avoid is having a Form expand to enormous proportions, so some ability to constrain the size of the Form is desired. The solution I present below has two methods to control the maximum size of the Form.

Similarly, when presenting a very small grid, having the Form contract to such a small size that other controls on the Form are not visible would not be desirable.

I wrote this method to support a WinForms application that needs to present a grid and a few buttons in a dialog. It appears to work well in this capacity though I'm unsure how well-suited it would be for use in a main Form. I have also not tried it with more than one DataGridView on one Form.

Using the Code

Download the attached source code and include it in your project.

Before calling this method, please be sure you have all the properties of the DataGridView set the way you like. For instance, if you are going to hide columns or enable row and column auto-resizing, you should do so before calling this method.

Similarly, be sure that the MinimumSize and MaximumSize properties of the Form are set the way you want before calling this method.

The method also accepts a Rectangle to use as a constraint which limits the Form to an area of the user's screen(s). A constraint is similar to setting the MaximumSize of the Form, but it also allows the Form to be moved. For the application I'm working on, I use System.Windows.Forms.Screen.FromControl ( Grid ).Bounds as a constraint to ensure that the Form stays on one physical monitior; the user may then manually resize the Form beyond that size. A value of System.Drawing.Rectangle.Empty acts as "no constraint".

If you do not constrain the Form with either MaximumSize or a Constraint rectangle, then the user may wind up with a very large Form that extends well beyond his physical monitor(s). Please be sure that that is the desired behaviour before you release such an application to your users.

There are some other options that can be specified and I'll discuss them as we go along. The options are bitmapped flags, of course.

Example:

C#
PIEBALD.Lib.LibWin.ResizeFormToFitDataGridView
(
  myGrid
,
  System.Drawing.Rectangle.Empty
,
  PIEBALD.Lib.LibWin.ResizeFormOption.HonorMinimumSize
  |
  PIEBALD.Lib.LibWin.ResizeFormOption.HonorMaximumSize
) ;

ResizeFormToFitDataGridView

The process of calculating the size required to show the whole grid is pretty simple.

Calculate the desired width

C#
int width  = lagniappe ;

/* Add the current width of the form outside the Grid */
width += form.Width - Grid.Width ;

/* Add the width of the row headers */
width += Grid.RowHeadersWidth ;

/* Add each visible column's width */
for ( int i = 0 ; i < Grid.ColumnCount ; i++ )
{
  if ( Grid.Columns [ i ].Visible )
  {
    width += Grid.Columns [ i ].Width ;
  }
}

Calculate the desired height

C#
int height = lagniappe ;

/* Add the current height of the form outside the Grid */
height += form.Height - Grid.Height ;

/* Add the height of the column headers */
height += Grid.ColumnHeadersHeight ;

/* Add each visible row's height */
for ( int i = 0 ; i < Grid.RowCount ; i++ )
{
  if ( Grid.Rows [ i ].Visible )
  {
    height += Grid.Rows [ i ].Height ;
  }
}

lagniappe is a constant that I add in order to avoid scroll bars in certain situations; you may need to adjust it, but the value 2 works on my system.

This gives us the total width and height required to show the whole grid, but it may be too small or too big, so...

Honor the MinimumSize of the Form when requested

HonorMinimumSize is an option that can be specified.

C#
if ( ( Options & ResizeFormOption.HonorMinimumSize ) == ResizeFormOption.HonorMinimumSize )
{
  if ( width < form.MinimumSize.Width )
  {
    width = form.MinimumSize.Width ;
  }

  if ( height < form.MinimumSize.Height )
  {
    height = form.MinimumSize.Height ;
  }
}

Honor the MaximumSize of the Form when requested

HonorMaximumSize is an option that can be specified.

C#
if ( ( Options & ResizeFormOption.HonorMaximumSize ) == ResizeFormOption.HonorMaximumSize )
{
  if ( ( form.MaximumSize.Width > 0 ) && ( width > form.MaximumSize.Width ) )
  {
    width = form.MaximumSize.Width ;
  }

  if ( ( form.MaximumSize.Height > 0 ) && ( height > form.MaximumSize.Height ) )
  {
    height = form.MaximumSize.Height ;
  }
}

maxsize

This size is saved as the maxsize.

Apply Constraint when requested

Provide a Rectangle other than Rectangle.Empty to apply a constraint. No validation of the constraint will be performed; please be sure to provide a meaningful rectangle.

C#
if ( Constraint != System.Drawing.Rectangle.Empty )
{
  /* If the preferred width won't fit the Constraint */
  if ( width > Constraint.Width )
  {
    /* slide it all the way to the left */
    form.Left = Constraint.X ;

    /* and clip the size to extend only to the right edge */
    width = Constraint.Left + Constraint.Width - form.Left ;
  }
  /* If the preferred width would extend beyond the right edge of the Constraint, */
  else if ( width > Constraint.Left + Constraint.Width - form.Left )
  {
    /* slide the Form toward the left */
    form.Left -= width - ( Constraint.Left + Constraint.Width - form.Left ) ;
  }

  /* If the preferred height won't fit the Constraint */
  if ( height > Constraint.Height )
  {
    /* slide it all the way to the top */
    form.Top = Constraint.Y ;

    /* and clip the size to extend only to the bottom edge */
    height = Constraint.Y + Constraint.Height - form.Top ;
  }
  /* If the preferred height would extend beyond the bottom edge of the Constraint, */
  else if ( height > Constraint.Top + Constraint.Height - form.Top )
  {
    /* slide the Form toward the top */
    form.Top -= height - ( Constraint.Y + Constraint.Height - form.Top ) ;
  }
}

minsize

This size is saved as the minsize and we try to resize the Form to this size.

Handling ArgumentOutOfRangeExceptions

Throw is an option that can be specified. Resizing the Form may throw an ArgumentOutOfRangeException, and the caller may choose whether or not to swallow such an exception once it has been caught. If this option is not specified, and this type of exception is encountered, then the return value will be set to false.

C#
/* Resizing across screen boundaries may cause ArgumentOutOfRangeExceptions */
catch ( System.ArgumentOutOfRangeException err )
{
  if ( ( Options & ResizeFormOption.Throw ) == ResizeFormOption.Throw )
  {
    err.Data [ "Top"    ] = form.Top  ;
    err.Data [ "Left"   ] = form.Left ;
    err.Data [ "Width"  ] = width     ;
    err.Data [ "Height" ] = height    ;

    throw ;
  }

  result = false ;
}

Freeze the Form when requested

Freeze is an option that can be specified. This will set the MaximumSize and MinimumSize properties of the Form, and, if they are equal, it will set the FormBorderStyle to fixed. This limits the ability of the user to manually resize the Form.

A Form that expands well beyond the user's physical monitor(s) and then becomes non-resizable would be considered user-hostile, so please don't Freeze a Form unless you have also constrained it to a reasonable size. You have been warned.

C#
if ( ( Options & ResizeFormOption.Freeze ) == ResizeFormOption.Freeze )
{
  form.MaximumSize = maxsize ;
  form.MinimumSize = minsize ;

  if ( minsize == maxsize )
  {
    switch ( form.FormBorderStyle )
    {
      case System.Windows.Forms.FormBorderStyle.Sizable :
      {
        form.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle ;

        break ;
      }

      case System.Windows.Forms.FormBorderStyle.SizableToolWindow :
      {
        form.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow ;

        break ;
      }
    }
  }
}

Conclusion

This method does what I need it to on my system, but I have also seen it behave a little oddly (nothing catastrophic) on a colleague's system and I haven't yet spent any time tracking down the cause -- I think it's due mainly to Windows themes, but I could be wrong.

I have performed only minimal testing and not thrown unusual values at it. Any feedback on how it behaves on your system(s) would be appreciated.

History

  • 2016-01-03 First submitted

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)