Infragistics WebDataGrid crashes if its total width over 32767 pixels

When you’re dealing with Infragistics WebDataGrid and want to manipulate appearance of individual columns – there’s a handy Columns collection for that. Unfortunately it’s available only if you define columns at design time or add columns to it in code-behind. If your grid features autogenerated columns – the collection will be empty.

There’s a way to derive column info tho – and can be done from grid row. The example below uses grid’s PreRender event to capture first row from which columns are derived and their width set:

Protected Sub xmyGrid_PreRender(sender As Object, e As EventArgs) Handles myGrid.PreRender
   Dim oGrid As GridControls.ContainerGrid
   Dim oRow As GridControls.ContainerGridRecord

   oGrid = sender
   oRow = oGrid.Rows(0)

   If oRow IsNot Nothing Then
      InitGridColumns(oRow) 'passing 1st grid row to helper sub
   End If
End Sub

Sub InitGridColumns(i_oRow As GridControls.ContainerGridRecord)
   Dim oGridCol As GridControls.BoundDataField

   'looping thru row cells
   For I As Integer = 0 To i_oRow.Items.Count - 1
       oGridCol = i_oRow.Items(I).Column 'deriving column object from row cell
       oGridCol.Width = Unit.Pixel(CalculateWidthHere()) 'setting calculated width
   Next
End Sub

This works pretty well – that is until summary width of all columns combined hit’s 32K. If this happens – grid crashes:

[ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: value]
System.Web.UI.WebControls.Unit..ctor(Int32 value) +3286406
System.Web.UI.WebControls.Unit.Pixel(Int32 n) +30
Infragistics.Web.UI.GridControls.WebDataGrid.ProjectedInnerTableWidth() +1642
Infragistics.Web.UI.GridControls.GridRenderer.RenderContents(HtmlTextWriter writer) +730
Infragistics.Web.UI.GridControls.ContainerGridRenderer.RenderContents(HtmlTextWriter writer) +392
Infragistics.Web.UI.GridControls.HierarchicalGridRenderer.RenderContents(HtmlTextWriter writer) +1096
Infragistics.Web.UI.Framework.RunBot.HandleRenderContents(HtmlTextWriter writer, RendererBase renderer) +220
Infragistics.Web.UI.Framework.Data.HierarchicalDataBoundControlMain.RenderContents(HtmlTextWriter writer) +104
Infragistics.Web.UI.Framework.Data.HierarchicalDataBoundControlMain.Render(HtmlTextWriter writer) +60

According to Infragistics this happens because grid uses Unit.Pixel structure to hold inner grid width and for some divine reason Microsoft limited it to Int16 (even though argument for Unit.Pixel is Int32).

You may think (I definitely did) that having a grid of this width is an impossible scenario (who would be able to read, use it?) but after seeing tables with 90 colums, 400px each in real-life applications I believe everything is possible.

Since I can’t control how Infragistics calculates grid metrics internally and cannot change god-given size of Unit.Pixel – time for some graceful degradation. What we can do is calculate by how much our grid width overshot 32K limit and reduce the width by evenly splitting reduction across all columns:

Sub InitGridColumns(i_oRow As GridControls.ContainerGridRecord)
   Dim oGridCol As GridControls.BoundDataField
   Dim iTotalColumnWidth As Integer = 0

   Const MAX_GRID_WIDTH As Integer = 32767

   'looping thru row cells
   For I As Integer = 0 To i_oRow.Items.Count - 1
       oGridCol = i_oRow.Items(I).Column 'deriving column object from row cell
       oGridCol.Width = Unit.Pixel(CalculateWidthHere()) 'setting calculated width
       iTotalColumnWidth += oGridCol.Width.Value 'accumulating total width
   Next

   If iTotalColumnWidth > MAX_GRID_WIDTH Then
      Dim iPercentReduce As Double = MAX_GRID_WIDTH / iTotalColumnWidth

      For I As Integer = 0 To i_oRow.Items.Count - 1
          oGridCol = i_oRow.Items(I).Column
          oGridCol.Width = Unit.Pixel(oGridCol.Width.Value * iPercentReduce)
      Next

  End If
End Sub

Here we detect if summary column width is over 32K (say 36000) – we calculate how much of current width it need be (percentage wise 0.91 in this example) and apply this percentage to each column (so column of original 400px width becomes 364px). Accumulated change brings us below threshold which avoids crash.

Leave a Reply

Your email address will not be published. Required fields are marked *