Re: how-to autosize the width of a column in a DataGrid

Discussion in 'Microsoft VB .NET' started by Herfried K. Wagner [MVP], Sep 5, 2003.

  1. Herfried K. Wagner [MVP], Sep 5, 2003
    #1
    1. Advertisements

  2. Herfried K. Wagner [MVP]

    Slonjo Guest

    I've placed an adapted version of this autosize code into an inherited
    datagrid class .

    I am noticing that when you call this autosize code multiple times,
    you get 'phantom' columns that are duplicates of the originals. I
    call them phantoms because when you check the locals window or the
    code in debug mode, the grid thinks it only has the original number of
    columns. Also, these additional columns are not 'autosized' as the
    originals are.

    Each time I call the autosize code, a new group of phantom columns is
    added to the end of the grid???

    Something to do with the CreateGraphics call I think.

    Any ideas?

    I've pasted my Grid class below.

    ================================================================================
    Option Explicit On
    Option Strict On
    Public Class Grid
    ' every function in this library requires the grid
    ' to have a tablestyle and a datatable or dataview as it's
    datasource.
    ' if no tablestyle is detected, one is automatically created.
    '
    ' 20030911 DLD
    Inherits Windows.Forms.DataGrid

    Private m_strTableStyleRef As String = "0"

    Sub New()
    Me.New(False)
    End Sub

    Sub New(ByVal bolSetDefaultProperties As Boolean)
    MyBase.New()
    If bolSetDefaultProperties Then SetDefaultProperties()
    End Sub

    Public Property TableStyleRef() As String
    Get
    Return m_strTableStyleRef
    End Get
    Set(ByVal Value As String)
    m_strTableStyleRef = Value
    End Set
    End Property

    Private ReadOnly Property _ts() As Windows.Forms.DataGridTableStyle
    Get
    Dim lts As Windows.Forms.DataGridTableStyle
    Try
    If IsNumeric(TableStyleRef) Then
    lts = Me.TableStyles(CInt(TableStyleRef))
    Else
    lts = Me.TableStyles(TableStyleRef)
    End If

    Catch exc As Exception
    If lts Is Nothing Then
    ' if no tablestyle is assigned, create and add one...
    lts = New Windows.Forms.DataGridTableStyle(True)
    lts.MappingName = _dt.TableName
    TableStyleRef = lts.MappingName
    TableStyles.Add(lts)
    CreateColumnMappings()
    End If
    Finally
    'lts = Nothing
    End Try
    Return lts
    End Get
    End Property

    Private ReadOnly Property _dt() As DataTable
    Get
    If TypeOf Me.DataSource Is DataTable Then
    Return DirectCast(Me.DataSource, DataTable)
    ElseIf TypeOf Me.DataSource Is DataView Then
    Return DirectCast(Me.DataSource, DataView).Table
    End If
    End Get
    End Property

    Private ReadOnly Property _RowCount() As Integer
    Get
    If TypeOf Me.DataSource Is DataTable Then
    Return DirectCast(Me.DataSource, DataTable).Rows.Count
    ElseIf TypeOf Me.DataSource Is DataView Then
    Return DirectCast(Me.DataSource, DataView).Count
    End If
    End Get
    End Property

    Public Sub SetDefaultProperties()
    Try
    With Me
    .Hide()
    .AllowSorting = True
    .BorderStyle = Windows.Forms.BorderStyle.None
    .CaptionText = String.Empty
    .CaptionVisible = False
    .ColumnHeadersVisible = True
    '.DataSource = Nothing
    .Enabled = True
    '.FlatMode = True
    .ForeColor = System.Drawing.Color.Navy
    .GridLineStyle = Windows.Forms.DataGridLineStyle.Solid
    '.GridLineColor=
    '.ReadOnly = True
    .RowHeadersVisible = True
    '.TabStop = False
    '.Visible = False
    '.ResumeLayout()
    .Visible = True
    End With
    Finally
    End Try
    End Sub

    #Region "Save/Load Column Widths"

    Function LoadSettings() As Boolean
    Dim cs As Windows.Forms.DataGridColumnStyle
    Try
    Dim enu As IEnumerator = _ts.GridColumnStyles.GetEnumerator
    While enu.MoveNext()
    cs = CType(enu.Current, System.Windows.Forms.DataGridColumnStyle)
    cs.Width = CInt(D.Registry.RegistryRead(Microsoft.Win32.RegistryHive.CurrentUser,
    D.CommonLib.g_strAppRegPath & "Grids\" & Me.Name,
    CStr(cs.MappingName)))
    If cs.Width = 0 Then cs.Width = 70
    End While
    Return True
    Catch exc As Exception
    'D.ExceptionHandler.HandleExc(exc, False)
    Finally
    cs = Nothing
    End Try
    End Function

    Function SaveSettings() As Boolean
    Dim cs As Windows.Forms.DataGridColumnStyle
    Try
    Dim enu As IEnumerator = _ts.GridColumnStyles.GetEnumerator
    While enu.MoveNext()
    cs = CType(enu.Current, System.Windows.Forms.DataGridColumnStyle)
    D.Registry.RegistryWrite(Microsoft.Win32.RegistryHive.CurrentUser,
    D.CommonLib.g_strAppRegPath & "Grids\" & Me.Name,
    CStr(cs.MappingName), cs.Width.ToString)
    End While
    Return True
    Catch exc As Exception
    'D.ExceptionHandler.HandleExc(exc, False)
    Finally
    cs = Nothing
    End Try
    End Function
    #End Region

    #Region "Autosize Columns"

    Public Sub AutoSizeColumnsToHeaderText()
    AutoSizeColumnsToHeaderText(False)
    End Sub

    Public Sub AutoSizeColumnsToHeaderText(ByVal bolLeaveZeroWidthColumns
    As Boolean)
    ' a tablestyle must already be created.
    Dim intMaxLength As Integer
    Dim colStyle As Windows.Forms.DataGridColumnStyle
    Dim g As System.Drawing.Graphics
    Try
    For Each colStyle In _ts.GridColumnStyles
    ' the MeasureString function returns
    ' the Width of the text in pixels
    ' taking the text's font into consideration.

    ' set colStyle.Width = to length of header text
    If colStyle.Width = 0 And bolLeaveZeroWidthColumns Then
    Else
    intMaxLength = CInt(Me.CreateGraphics.MeasureString(colStyle.HeaderText.ToString,
    Me.Font).Width) + 5
    colStyle.Width = intMaxLength
    End If
    intMaxLength = 0
    Next
    Catch exc As Exception
    D.ExceptionHandler.HandleExc(exc, True)
    Finally
    colStyle.Dispose()
    End Try
    End Sub

    Public Sub AutoSizeColumns()
    AutoSizeColumns(False)
    End Sub

    Public Sub AutoSizeColumns(ByVal bolLeaveZeroWidthColumns As Boolean)
    Dim intColCounter As Integer = 0
    Dim intCols As Integer

    Try
    intCols = _dt.Columns.Count
    If intCols = 0 Then Exit Try
    Do While (intColCounter < intCols)
    If _ts.GridColumnStyles(intColCounter).Width = 0 And
    bolLeaveZeroWidthColumns Then
    Else
    AutoSizeColumn(intColCounter)
    End If
    intColCounter += 1
    Loop
    Catch exc As Exception
    Finally
    End Try
    End Sub

    Public Sub AutoSizeColumns(ByVal intStartingCol As Integer, ByVal
    intEndCol As Integer)
    Dim intColCounter As Integer
    Try
    intColCounter = intStartingCol
    Do While (intColCounter <= intEndCol)
    AutoSizeColumn(intColCounter)
    intColCounter += 1
    Loop
    Catch exc As Exception
    Finally
    End Try
    End Sub

    Public Sub AutoSizeColumn(ByVal intColIndex As Integer)
    Dim sngWidth As Single = 0
    'Dim intRows As Integer = 0
    Dim intRowCounter As Integer = 0
    Dim g As System.Drawing.Graphics
    Dim sf As System.Drawing.StringFormat
    Dim sizeColText As System.Drawing.SizeF
    Dim chrSearchChar As Char = " "c
    Dim sngCharCount As Single

    Try
    ' if there aren't any rows,
    ' there isn't any text to measure.
    ' Fall through and use the header text
    ' to set the column width
    If _RowCount > 0 Then
    g = System.Drawing.Graphics.FromHwnd(Me.Handle)
    sf = New System.Drawing.StringFormat(System.Drawing.StringFormat.GenericTypographic)
    ' loop all rows to find width of the largest value in the column
    Do While (intRowCounter < _RowCount)
    sizeColText = g.MeasureString(Me(intRowCounter,
    intColIndex).ToString, Me.Font, 500, sf)
    If (sizeColText.Width > sngWidth) Then
    sngWidth = sizeColText.Width
    ' now we are looking for spaces
    ' the MeasureString call above seems to ignore spaces
    ' even though they take up length???
    ' here we calc the number of spaces in the string
    ' and add a bit to the width for each space found
    sngCharCount = Me(intRowCounter,
    intColIndex).ToString.Split(chrSearchChar).GetUpperBound(0)
    sngWidth += (sngCharCount * 7)
    End If
    intRowCounter += 1
    Loop
    End If
    ' grab the length of the header text
    Dim sizeHeaderText As System.Drawing.SizeF =
    g.MeasureString(_ts.GridColumnStyles(intColIndex).HeaderText, Me.Font)
    ' if the header text is wider than any of the column's values...
    ' use it's width as the column width
    ' so that at least the header text is visible.
    If sngWidth < sizeHeaderText.Width Then sngWidth =
    CSng(sizeHeaderText.Width)
    ' finally, set the column width and add a bit for good measure (no
    pun)
    _ts.GridColumnStyles(intColIndex).Width = CInt(sngWidth) + 8
    Catch exc As Exception
    D.ExceptionHandler.HandleExc(exc)
    Finally
    g.Dispose()
    g = Nothing
    sf.Dispose()
    sf = Nothing
    sizeColText = Nothing
    End Try

    End Sub

    Private Sub CreateColumnMappings()
    Dim cs As Windows.Forms.DataGridColumnStyle
    Dim col As DataColumn
    Dim i As Integer = 0
    Try
    For Each col In _dt.Columns
    Me.TableStyles(TableStyleRef).GridColumnStyles(i).MappingName =
    col.ColumnName
    i += 1
    Next
    Catch exc As Exception
    D.ExceptionHandler.HandleExc(exc)
    Finally
    cs = Nothing
    col = Nothing
    End Try
    End Sub

    #End Region

    'Public Sub AutoSizeColumn(ByVal intColIndex As Integer)
    ' Dim sngWidth As Single = 0
    ' Dim intRows As Integer = 0
    ' Dim g As System.Drawing.Graphics
    ' Dim sf As System.Drawing.StringFormat
    ' Dim sizeColText As System.Drawing.SizeF
    ' Dim intRowCounter As Integer = 0
    ' Dim ts As Windows.Forms.DataGridTableStyle
    ' Try
    ' ts = Me.TableStyles(0)
    ' Try
    ' intRows = dt.Rows.Count
    ' If intRows = 0 Then Exit Try
    ' 'If TypeOf Me.DataSource Is DataTable Then
    ' ' intRows = CType(Me.DataSource, DataTable).Rows.Count
    ' 'ElseIf TypeOf Me.DataSource Is DataView Then
    ' ' intRows = CType(Me.DataSource, DataView).Table.Rows.Count
    ' 'End If

    ' g = System.Drawing.Graphics.FromHwnd(Me.Handle)
    ' sf = New System.Drawing.StringFormat(System.Drawing.StringFormat.GenericTypographic)

    ' Do While (intRowCounter < intRows)
    ' sizeColText = g.MeasureString(Me(intRowCounter,
    intColIndex).ToString, Me.Font, 500, sf)
    ' If (sizeColText.Width > sngWidth) Then
    ' sngWidth = sizeColText.Width
    ' End If
    ' intRowCounter += 1
    ' Loop
    ' ts.GridColumnStyles(intColIndex).Width = CInt(sngWidth) + 5
    ' Catch exc As Exception
    ' D.ExceptionHandler.HandleExc(exc)
    ' Finally
    ' g.Dispose()
    ' g = Nothing
    ' sf.Dispose()
    ' sf = Nothing
    ' sizeColText = Nothing
    ' End Try
    ' Catch ex As Exception
    ' Finally
    ' End Try
    'End Sub
    End Class
    ================================================================================
     
    Slonjo, Sep 16, 2003
    #2
    1. Advertisements

  3. Herfried K. Wagner [MVP]

    Slonjo Guest

    I also found that this happens after hitting my "autogenerate tablestyle" code.

    More debugging required.

    Nevermind.


    (Slonjo) wrote in message news:<>...
    > I've placed an adapted version of this autosize code into an inherited
    > datagrid class .
    >
    > I am noticing that when you call this autosize code multiple times,
    > you get 'phantom' columns that are duplicates of the originals.
     
    Slonjo, Sep 16, 2003
    #3
    1. Advertisements

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. One Handed Man

    Re: how-to autosize the width of a column in a DataGrid

    One Handed Man, Sep 5, 2003, in forum: Microsoft VB .NET
    Replies:
    0
    Views:
    464
    One Handed Man
    Sep 5, 2003
  2. one

    How to Autosize DataGrid Columns

    one, Feb 20, 2004, in forum: Microsoft VB .NET
    Replies:
    1
    Views:
    208
    Herfried K. Wagner [MVP]
    Feb 20, 2004
  3. Guest

    Datagrid autosize

    Guest, May 4, 2004, in forum: Microsoft VB .NET
    Replies:
    1
    Views:
    204
    Ken Tucker [MVP]
    May 4, 2004
  4. Guest

    Autosize columns of DataGrid

    Guest, Nov 9, 2005, in forum: Microsoft VB .NET
    Replies:
    1
    Views:
    448
    Cor Ligthert [MVP]
    Nov 9, 2005
  5. eBob.com
    Replies:
    2
    Views:
    765
    Jack Jackson
    Apr 16, 2009
Loading...

Share This Page