Comment redimensionner automatiquement les colonnes dans un contrôle DataGridView ET permettre à l'utilisateur de redimensionner les colonnes sur cette même grille?


109

Je remplis un contrôle DataGridView sur un formulaire Windows (C # 2.0 et non WPF).

Mon objectif est d'afficher une grille qui remplit parfaitement toute la largeur disponible avec des cellules - c'est-à-dire aucune zone inutilisée (gris foncé) en bas à droite et dimensionne chaque colonne de manière appropriée en fonction des données qu'elle contient, mais permet également à l'utilisateur de redimensionner l'une des colonnes. à leur goût.

J'essaie d'y parvenir en définissant l'AutoSizeMode de chaque colonne sur DataGridViewAutoSizeColumnMode.AllCells, sauf pour l'une des colonnes que j'ai définies sur DataGridViewAutoSizeColumnMode.Fill afin de garantir que toute la zone de la grille est parfaitement remplie de données. (Cela ne me dérange pas que lorsque l'utilisateur tente de redimensionner cette colonne, il revient à une taille qui garantit que l'espace horizontal est toujours utilisé.)

Cependant, comme je l'ai mentionné, une fois chargé, je voudrais permettre à l'utilisateur de redimensionner les colonnes en fonction de ses propres besoins - en définissant ces valeurs AutoSizeMode pour chaque colonne, il semble que l'utilisateur ne soit pas en mesure de redimensionner ces colonnes.

J'ai essayé de ne pas définir l'AutoSizeMode de toutes les colonnes, ce qui permet le redimensionnement MAIS ne définit pas la taille initiale en fonction des données que les cellules contiennent. Le même résultat se produit lors de la modification du mode AutoSizeMode de la grille sur «Non défini» après le chargement des données.

Y a-t-il un paramètre qui me manque ici qui permet le réglage automatique des largeurs de colonne par défaut ET le redimensionnement de l'utilisateur ou y a-t-il une autre technique que je dois utiliser lors du remplissage du contrôle DataGridView?


ne le définissez pas sur "Non défini" réglez-le sur "Aucun" pour que le redimensionnement ne revienne pas Retour - testé pour c #, .net2.0
bh_earth0

Réponses:


132

Cette astuce fonctionne pour moi:

grd.DataSource = DT;

//set autosize mode
grd.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
grd.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
grd.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

//datagrid has calculated it's widths so we can store them
for (int i = 0; i <= grd.Columns.Count - 1; i++) {
    //store autosized widths
    int colw = grd.Columns[i].Width;
    //remove autosizing
    grd.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
    //set width to calculated by autosize
    grd.Columns[i].Width = colw;
}

Ce qui se passe ici, c'est que vous définissez la taille automatique sur le mode dont vous avez besoin, puis, colonne par colonne, vous stockez la largeur obtenue à partir du calcul de la taille automatique, supprimez la taille automatique et définissez la largeur sur la valeur que vous avez stockée auparavant.


1
J'ai mis un code similaire dans une routine nommée AutoResizeColumnWidthsYetAllowUserResizing. Il est appelé après le remplissage initial de la grille et également après que l'utilisateur a modifié les données (c'est-à-dire à partir de l'événement CellEndEdit de la grille).
DeveloperDan

5
C'est un excellent code. Doit être placé dans l'événement «DataGridView1_DataSourceChanged».
user890332

1
Il me semble que faire ça grd.Columns(i).Width = grd.Columns(i).Widthfera déjà l'affaire. Regardez ici .
Antonio

2
pour c # similaire mais avec crochets dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
barlop

Cela aurait pu arriver très tard, mais par hasard ou par moyen, nous pourrions redimensionner en fonction du contenu d'une ligne particulière? Disons, en fonction du contenu des cellules de la première ligne, quelle que soit la largeur des cellules des autres lignes?
Murtuza Husain

45

Peut-être que tu pourrais appeler

dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.Fill);

Après avoir défini la source de données. Il définira la largeur et autorisera le redimensionnement.

Plus d'informations sur la méthode MSDN DataGridView.AutoResizeColumns (DataGridViewAutoSizeColumnsMode) .


2
Je ne sais pas pourquoi cette réponse ne retient pas davantage l'attention. Beaucoup plus propre. Bien que si vous cherchez à faire correspondre la largeur du contenu de la cellule, DataGridViewAutoSizeColumnsMode.AllCells fonctionne un peu mieux.
iwalkbarefoot

31
en utilisant cette solution, j'obtiens l' erreur suivante: "Le paramètre autoSizeColumnMode n'est pas valide pour cette opération. Il ne peut pas être NotSet, None ou Fill mais doit indiquer un critère de dimensionnement." . J'ai fini par utiliser ce dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
itsho

6
L'utilisation de DataGridViewAutoSizeColumnMode.Fill ne fonctionne pas car il ignore le contenu de la cellule lors du dimensionnement des colonnes.
Stuart Helwig

J'ai utilisé cette méthode avec DataGridViewAutoSizeColumnsMode.DisplayedCells. En outre, dans le Concepteur de formulaires, AutoSizeColumnsMode est défini sur Aucun. J'avais besoin d'exécuter cet appel de méthode dans le gestionnaire d'événements DataBindingComplete de DataGridView, pour m'assurer qu'il (re) dimensionnait toujours correctement.
Daan

7
Je ne comprends pas tous les votes positifs ... Cela ne fonctionne pas du tout, la documentation MSDN est claire, cela conduit à une ArgumentException si le autoSizeColumnsMode a la valeur None ou Fill.
Larry

31

Version AC # du code de Miroslav Zadravec

for (int i = 0; i < dataGridView1.Columns.Count-1; i++)
{
    dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
}
dataGridView1.Columns[dataGridView1.Columns.Count - 1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

for (int i = 0; i < dataGridView1.Columns.Count; i++)
{
    int colw = dataGridView1.Columns[i].Width;
    dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
    dataGridView1.Columns[i].Width = colw;
}

Publié en tant que Wiki communautaire pour ne pas perdre la réputation des autres


15

Dans mon application, j'ai défini

grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
grid.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;

Aussi, j'ai défini le

grid.AllowUserToOrderColumns = true;
grid.AllowUserToResizeColumns = true;

Maintenant, les largeurs de colonne peuvent être modifiées et les colonnes peuvent être réorganisées par l'utilisateur. Cela fonctionne plutôt bien pour moi.

Peut-être que cela fonctionnera pour vous.


Définir AutoSizeColumnsMode de la grille sur "Fill" semble définir toutes les colonnes sur les mêmes largeurs. Oui, les colonnes sont alors redimensionnables mais les largeurs initiales sont toutes fausses. Je devrai peut-être définir les largeurs de colonne dans le code "manuellement".
Stuart Helwig

DV- grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumn-> s <- Mode.Fill; (vous avez manqué le s, c'est ColumsMode sur le côté gauche et le côté droit, de sorte que votre ligne ne se compile pas) Le code pour obtenir le dimensionnement automatique de datagridview est très ennuyeux car il est, alors au moins vérifiez votre réponse d'abord . C'est la toute première ligne que vous avez écrite et elle est fausse.
barlop le

@barlop merci pour votre réponse. Vous avez le privilège de modifier les questions et réponses. Si vous remarquez une erreur dans mon code, n'hésitez pas à le modifier.
Jehof

12

Après avoir ajouté les données à la grille, ajoutez le code suivant qui ajustera la colonne en fonction de la longueur des données dans chaque cellule

dataGrid1.AutoResizeColumns();            
dataGrid1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;

Voici le résultat

entrez la description de l'image ici


9

Eh bien, j'ai fait ceci comme ceci:

dgvReport.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
dgvReport.AutoResizeColumns();
dgvReport.AllowUserToResizeColumns = true;
dgvReport.AllowUserToOrderColumns = true;

dans cet ordre particulier. Les colonnes sont redimensionnées (étendues) ET l'utilisateur peut redimensionner les colonnes par la suite.


6

Si j'ai bien compris la question, il devrait y avoir un moyen plus simple d'accomplir ce dont vous avez besoin. Appel dgvSomeDataGrid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);

Cela devrait faire l'affaire. Cependant, il existe un piège car vous ne pouvez pas simplement appeler cette méthode directement après avoir rempli votre contrôle DataGridView. Au lieu de cela, vous devrez ajouter un EventHandler pour l'événement VisibleChanged et appeler la méthode à l'intérieur.


1
Cela redimensionnerait les colonnes en fonction du contenu, mais ne garantirait pas que tout l'espace de grille disponible est utilisé. Ie, ne "remplit" pas l'espace restant s'il y en a.
Stuart Helwig

5

Un simple deux lignes de code fonctionne pour moi.

dataGridView.DataSource = dataTable;
dataGridView.AutoResizeColumns();

4

Reprise de la question:
faire adapter la largeur de la colonne au contenu (avec une méthode différente dans la colonne),
mais permettez ensuite à l'utilisateur de définir la largeur de la colonne ...

En se développant à partir de la réponse de Miroslav Zadravec , pour moi, ce qui a fonctionné était immédiatement d'utiliser l'auto calculé column.Widthpour définir ... column.Width!

foreach (DataGridViewColumn column in dataGridView.Columns)
{
    if (/*It's not your special column*/)
    {
        column.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
        column.Width = column.Width; //This is important, otherwise the following line will nullify your previous command
        column.AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet;
    }
}

//Now do the same using Fill instead of AllCells for your special column

Ceci est testé pour fonctionner lorsque le DataGridViewest déjà créé, en utilisant une astuce comme celle-ci .


Je préfère utiliser un foreach comme le fait votre code. Cela le rend plus lisible lorsque vous n'avez pas de maths en haut de la boucle. Je l'ai fait de cette façon, et le "column.Width = column.Width;" est intéressant.
Greg Barth

4

Cela a fait des merveilles pour moi:

dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);

1
Solution simple!
Mark Kram

1
A travaillé pour moi uniquement si défini sur Aucun par la suite, c'est dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
-à-

3

Cela ajuste automatiquement toutes les colonnes en fonction de leur contenu, remplit l'espace vide restant en étirant une colonne spécifiée et empêche le comportement de «saut» en définissant la dernière colonne à remplir pour tout redimensionnement futur.

// autosize all columns according to their content
dgv.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
// make column 1 (or whatever) fill the empty space
dgv.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
// remove column 1 autosizing to prevent 'jumping' behaviour
dgv.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
// let the last column fill the empty space when the grid or any column is resized (more natural/expected behaviour) 
dgv.Columns.GetLastColumn(DataGridViewElementStates.None, DataGridViewElementStates.None).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

Je sais que c'est une vieille réponse, mais je fonctionne bien, même lorsque le nombre de colonnes n'est pas connu à l'avance.
Nilo Paim

2

Code C # légèrement plus soigné du code de Miroslav Zadravec en supposant que toutes les colonnes doivent être auto-dimensionnées

for (int i = 0; i < dgvProblems.Columns.Count; i++)
{
    dgvProblems.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
    int colw = dgvProblems.Columns[i].Width;
    dgvProblems.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
    dgvProblems.Columns[i].Width = colw;
}

2

Une autre version du code de Miroslav Zadravec, mais légèrement plus automatisée et universelle:

    public Form1()
    {
        InitializeComponent();
        dataGridView1.DataSource = source;
        for (int i = 0; i < dataGridView1.Columns.Count - 1; i++) {
            dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
        }
        dataGridView1.Columns[dataGridView1.Columns.Count].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

    }

    void Form1Shown(object sender, EventArgs e)
    {
        for ( int i = 0; i < dataGridView1.Columns.Count; i++ )
        {
            int colw = dataGridView1.Columns[i].Width;
            dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
            dataGridView1.Columns[i].Width = colw;
        }
    }

Je mets la deuxième partie dans un événement séparé, car je remplis l' datagridvewinitialisation du formulaire et si les deux parties sont là, rien ne change, car le dimensionnement automatique calcule probablement les largeurs après l' datagridviewaffichage, donc les largeurs sont toujours par défaut dans la Form1()méthode. Après avoir terminé cette méthode, la taille automatique fait son tour et immédiatement après cela (lorsque le formulaire est affiché), nous pouvons définir les largeurs par seconde partie du code (ici en Form1Showncas). Cela fonctionne pour moi comme un charme.


2

Voici un code simplifié pour la réponse de Miroslav Zadravec en c #:

CurrentDGV.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader;
for (int i = 0; i < dataGridView1.Columns.Count; i++) dataGridView1.Columns[i].Width = dataGridView1.Columns[i].Width;
CurrentDGV.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;

1

Avez-vous essayé de configurer la FillWeightpropriété de votreDataGridViewColumns objet?

Par exemple:

this.grid1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
this.grid1.Columns[0].FillWeight = 1.5;

Je pense que cela devrait fonctionner dans votre cas.


1

Une petite amélioration par rapport à la version de Schnapple

int nLastColumn = dgv.Columns.Count - 1;
for (int i = 0; i < dgv.Columns.Count; i++)
{
    if (nLastColumn == i)
    {
        dgv.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
    }
    else
    {
        dgv.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
    }
}

for (int i = 0; i < dgv.Columns.Count; i++)
{
    int colw = dgv.Columns[i].Width;
    dgv.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
    dgv.Columns[i].Width = colw;
}


1

Les largeurs de colonne définies pour s'adapter à son contenu J'ai utilisé l'instruction ci-dessous, cela a résolu mon problème.

Premier pas :

RadGridViewName.AutoSize = true;

Deuxième étape :

// This mode  fit in the header text and column data for all visible rows. 
this.grdSpec.MasterTemplate.BestFitColumns();

Troisième étape :

for (int i = 0; i < grdSpec.Columns.Count; i++) 
{
    // The column width adjusts to fit the contents all cells in the control.
    grdSpec.Columns[i].AutoSizeMode = BestFitColumnMode.AllCells; 
}

1
foreach (DataGridViewColumn c in dataGridView.Columns)
    c.Width = c.GetPreferredWidth(DataGridViewAutoSizeColumnMode.AllCells, true);

Cela devrait fonctionner que le dataGridViewait été affiché ou non (c'est-à-dire même s'il est appelé depuis le constructeur de classe).

La même méthode, mais avec DataGridViewAutoSizeColumnMode.DisplayedCells, échoue dans le cas ci-dessus pour la raison évidente - aucune cellule n'a encore été affichée! Pour une raison non évidente, AutoResizeColumnséchoue également dans ce cas.


0

Si vous liez votre source de données à une table de données par exemple, vous devez définir les propriétés une fois la liaison effectuée:

        private void dgv_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
            dgv.AutoResizeColumns();
            dgv.AllowUserToResizeColumns = true;
        }

0
  • Merci pour la solution ci-dessus (pour parcourir le DataGridView.Columns, passez AutoSizeModeà un valide, collectez la valeur de largeur et réinitialisez-la après le changement AutoSizeModedeDataGridViewAutoSizeColumnMode.None ).
  • J'ai eu du mal avec cela et j'ai remarqué que cela ne fonctionnait pas chaque fois qu'il était appelé à partir du constructeur de classe ou de toute ligne avant Form.Show()ou Form.ShowDialog(). J'ai donc mis cet extrait de code dans l' Form.Shownévénement et cela fonctionne pour moi.
  • Mon code transformé, sans reguard de tout ce qui a été DataGridView.AutoSizeColumnsModedéfini auparavant, j'utilise DataGridViewColumn.GetPreferredWidth()au lieu de changer DataGridViewColumn.AutoSizeModeet de définir la valeur de largeur immédiatement, puis de changer DataGridView.AutoSizeColumnsModeune fois:

    private void form_Shown(object sender, EventArgs e)
    {
            foreach (DataGridViewColumn c in dataGridView.Columns)
                c.Width = c.GetPreferredWidth(DataGridViewAutoSizeColumnMode.DisplayedCells, true);
            dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
    }
  • Assurez-vous de définir

            dataGridView.AllowUserToResizeColumns = true;
  • Je ne sais pas comment cela ne fonctionne qu'après l'affichage du formulaire.


0

Je devais le faire en VB et préférer le diviser en une méthode que j'ai placée dans un module. Vous pouvez ajouter la colonne Fill comme un autre paramètre ByRef si vous le souhaitez.

''' <summary>
''' Makes all columns in a DataGridView autosize based on displayed cells,
''' while leaving the column widths user-adjustable.
''' </summary>
''' <param name="dgv">A DataGridView to adjust</param>
Friend Sub MakeAdjustableAutoSizedGridCols(ByRef dgv As DataGridView)
    Dim width As Integer

    For Each col As DataGridViewColumn In dgv.Columns
        col.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells
        width = col.Width
        col.AutoSizeMode = DataGridViewAutoSizeColumnMode.None
        col.Width = width
    Next
    dgv.AllowUserToResizeColumns = True
End Sub

0

Vous pouvez faire quelque chose comme ceci:

   grd.DataSource = getDataSource();

    if (grd.ColumnCount > 1)
    {
        for (int i = 0; i < grd.ColumnCount-1; i++)
            grd.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;

        grd.Columns[grd.ColumnCount-1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
    }

    if (grd.ColumnCount==1)
        grd.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

Toutes les colonnes s'adapteront au contenu sauf la dernière remplira la grille.


0

Avec $ array étant le contenu d'un PSCustomObject, cela fonctionne:

$dataGridView1.DataSource=[collections.arraylist]($array)
$dataGridView1.Columns | Foreach-Object{$_.AutoSizeMode = [System.Windows.Forms.DataGridViewAutoSizeColumnMode]::AllCells}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.