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.