Redimensionner les colonnes d'un contrôle datagrid d'après son contenu

0/5 (2 avis)

Vue 13 434 fois - Téléchargée 1 086 fois

Description

Cette fonction permet d'ajuster la largeur des colonnes d'un contrôle DataGrid en fonction de leur contenu : entête de la colonne, contenu des enregistrements, en fonction de la police de caractères.

Pré-requis :
- il faut créer un TableStyle pour la DataTable associée à la grille en tant que DataSource.
- il faut créer un GridColumnStyle pour chaque colonne à afficher dans la grille, avec une taille (Width) > 0

Comportement :
- s'il n'y a pas de TableStyle associé à la grille pour DataSource, une exception est levée.
- si une colonne ne possède pas de GridColumnStyle, elle est ignorée lors du redimensionnement.
- si une colonne possède un GridColumnStyle avec une taille (Width) égale à 0, elle est ignorée lors du redimensionnement.

- fonctionne pour les DataGridTextBoxColumnStyle et les DatagridBoolColumnStyle, quel que soit le type de donnée de la colonne (Int16, Int32, String, Decimal, Double, etc...)
- la DataSource de la grille, peut être un DataView pointant sur un DataTable, un DataTable, un DataSet avec un des DataTable qu'il contient.

Jetez un coup d'oeil sur l'image en début.

Source / Exemple :


Private Sub DataGridColumnAutoResize(ByRef oDataGrid As DataGrid)
        Dim ds As DataSet
        Dim dt As DataTable
        Dim dw As DataView
        Dim row As DataRow
        Dim c As DataColumn
        Dim i As Integer
        Dim v() As Object
        Dim o As Object
        Dim maxcolsize() As Single
        Dim sg As Single
        Dim col_font As Font
        Dim header_font As Font
        Dim g As Graphics
        Dim s As String
        Dim tmp_sz As SizeF
        Dim nbcol As Integer = -1
        Dim nbgcs As Integer = -1
        Dim ColumnResizedIndexes() As Integer = Nothing
        Dim GridColumnStyleResizedIndexes() As Integer = Nothing

        ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        ' les colonnes dont la largeur (width) a été positionnée à 0 auparavant sont considérées
        ' comme masquées et sont laissées telles quelles
        ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

        ' la source de données doit être une Datatable, un Dataview ou un DataSet
        If TypeOf oDataGrid.DataSource Is DataTable Then
            dt = CType(oDataGrid.DataSource, DataTable)
        ElseIf TypeOf oDataGrid.DataSource Is DataView Then
            dw = CType(oDataGrid.DataSource, DataView)
            dt = dw.Table
        ElseIf TypeOf oDataGrid.DataSource Is DataSet Then
            ds = CType(oDataGrid.DataSource, DataSet)
            dw = Nothing
            dt = ds.Tables(oDataGrid.DataMember)
        Else
            Throw New Exception("DataGridColumnAutoResize : la source de données pour n'est pas valide.")
            Exit Sub
        End If

        Dim tabname As String = dt.TableName

        If Not oDataGrid.TableStyles.Contains(tabname) Then
            Throw New Exception("DataGridColumnAutoResize : le TableStyle '" + tabname + "' n'existe pas.")
            Exit Sub
        End If

        g = oDataGrid.CreateGraphics()

        i = 0
        For Each c In dt.Columns
            If oDataGrid.TableStyles(tabname).GridColumnStyles.Contains(c.ColumnName) Then
                nbgcs += 1
                If oDataGrid.TableStyles(tabname).GridColumnStyles(nbgcs).Width > 0 Then
                    nbcol += 1
                    ReDim Preserve ColumnResizedIndexes(nbcol)
                    ColumnResizedIndexes(nbcol) = i
                    ReDim Preserve GridColumnStyleResizedIndexes(nbcol)
                    GridColumnStyleResizedIndexes(nbcol) = nbgcs
                End If
            End If
            i += 1
        Next
        ReDim maxcolsize(nbcol)

        header_font = oDataGrid.TableStyles(tabname).HeaderFont

        ' la taille max de chaque colonne est initialisée avec la taille des entêtes
        nbcol = 0
        For Each i In GridColumnStyleResizedIndexes
            tmp_sz = g.MeasureString(oDataGrid.TableStyles(tabname).GridColumnStyles(i).HeaderText, _
                header_font)
            maxcolsize(nbcol) = tmp_sz.Width * (1 + (2 / tmp_sz.Width)) ' formule à la con ...
            nbcol += 1
        Next

        ' on tient enfin compte des données contenues dans la source de données liée au Datagrid
        For Each row In dt.Rows
            nbcol = 0
            If (Not (row.RowState = DataRowState.Deleted)) AndAlso (Not (row(0) Is DBNull.Value)) Then
                v = row.ItemArray
                i = 0
                For Each o In v
                    If [Array].IndexOf(ColumnResizedIndexes, i) <> -1 Then
                        Select Case [Type].GetTypeCode(o.GetType())
                            Case TypeCode.String
                                s = o
                            Case TypeCode.DateTime
                                s = CStr(o) ' conversion DateTime vers String, en enlevant l'heure
                            Case Else
                                s = o.ToString
                        End Select
                        col_font = oDataGrid.Font
                        tmp_sz = g.MeasureString(s, col_font)

                        sg = tmp_sz.Width * (1 + (2 / tmp_sz.Width)) ' formule à la con ...
                        If maxcolsize(nbcol) < sg Then
                            maxcolsize(nbcol) = sg
                        End If
                        nbcol += 1
                    End If
                    i = i + 1
                Next
            End If
        Next

        nbcol = 0
        For Each i In GridColumnStyleResizedIndexes
            oDataGrid.TableStyles(tabname).GridColumnStyles(i).Width = maxcolsize(nbcol)
            nbcol += 1
        Next

    End Sub

Conclusion :


Le redimensionnement ne fonctionne pas forcément bien si vous avez créé des ColumnStyle personnalisé, avec ComboBox, ou DateTimePicker, etc....

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
64
Date d'inscription
dimanche 24 juillet 2005
Statut
Membre
Dernière intervention
29 septembre 2014

Bonjour, et désolé de répondre deux ans après !
ca pourra servir à quelqu'un d'autre peut-être ...

la "formule à la con" sert à AUGMENTER légèrement la largeur de l'entête de colonne par rapport à la taille du texte qu'elle contient (ca n'est donc pas dégressif).
La raison ? si on ne fait pas ca, l'entête n'apparait pas complètement, le dernier caractère au moins est toujours "rogné". Ca doit être dû, à mon avis, au fait qu'un espace est automatiquement ajouté par le contrôle DATAGRID AVANT et APRES le texte dans l'entête de colonne. Donc Graphic.MeasureString ne suffit pas.
De plus, je ne sais pas comment récupérer cette valeur en temps réel, donc j'ai déterminé la "formule à la con" de manière empirique en faisant des essais (par dichotomie en quelque sorte).

Faites l'essai sans la "formule à la con", et vous verrez la différence.

Voilà voilà
Messages postés
215
Date d'inscription
jeudi 24 octobre 2002
Statut
Membre
Dernière intervention
7 septembre 2007
1
g.MeasureString(s, col_font)

pas mal pas mal ...

quelle est l'utilité de la formule à la con?
tmp_sz = g.MeasureString(s, col_font)
sg = tmp_sz.Width * (1 + (2 / tmp_sz.Width)) ' formule à la con ...
et entre nous soit dit, si le commentaire dit effectivement ce que c'est (une formule à la con donc), il eut été plus utile de dire le pourquoi du besoin de ce petit pourcentage (dégressif en plus apperemment) ajouté.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.