Come ridimensionare automaticamente le colonne in un controllo DataGridView E consentire all'utente di ridimensionare le colonne sulla stessa griglia?


109

Sto popolando un controllo DataGridView su un Windows Form (C # 2.0 non WPF).

Il mio obiettivo è quello di visualizzare una griglia che riempia in modo ordinato tutta la larghezza disponibile con le celle, ovvero nessuna area inutilizzata (grigio scuro) in basso a destra e ridimensiona ogni colonna in modo appropriato in base ai dati in essa contenuti, ma consente anche all'utente di ridimensionare qualsiasi colonna a loro piacimento.

Sto tentando di ottenere questo risultato impostando AutoSizeMode di ogni colonna su DataGridViewAutoSizeColumnMode.AllCells tranne per una delle colonne che ho impostato su DataGridViewAutoSizeColumnMode.Fill per garantire che l'intera area della griglia sia riempita in modo ordinato con i dati. (Non mi importa che quando l'utente tenta di ridimensionare questa colonna, ritorna a una dimensione che garantisce che lo spazio orizzontale venga sempre utilizzato.)

Tuttavia, come ho accennato, una volta caricato vorrei consentire all'utente di ridimensionare le colonne in base alle proprie esigenze: nell'impostazione di questi valori AutoSizeMode per ciascuna colonna sembra che l'utente non sia quindi in grado di ridimensionare quelle colonne.

Ho provato a non impostare AutoSizeMode di tutte le colonne che consente il ridimensionamento MA non imposta la dimensione iniziale in base ai dati contenuti nelle celle. Lo stesso risultato si verifica quando si modifica l'AutoSizeMode della griglia su "Non impostato" dopo aver caricato i dati.

C'è un'impostazione che mi manca qui che consente l'impostazione automatica delle larghezze delle colonne predefinite E il ridimensionamento dell'utente o c'è un'altra tecnica che devo usare quando popolo il controllo DataGridView?


non impostarlo su "Non impostato" impostalo su "Nessuno" in modo che il ridimensionamento non venga ripristinato Indietro - testato per c #, .net2.0
bh_earth0

Risposte:


132

Questo trucco funziona per me:

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;
}

Quello che succede qui è che imposti la dimensione automatica sulla modalità di cui hai bisogno e poi colonna per colonna memorizzi la larghezza ottenuta dal calcolo della dimensione automatica, rimuovi il dimensionamento automatico e imposta la larghezza sul valore memorizzato in precedenza.


1
Ho inserito un codice simile in una routine denominata AutoResizeColumnWidthsYetAllowUserResizing. Viene chiamato dopo che la griglia è stata popolata inizialmente e anche dopo che l'utente ha modificato i dati (ovvero dall'evento CellEndEdit della griglia).
Sviluppatore:

5
Questo è un ottimo codice. Deve essere inserito nell'evento "DataGridView1_DataSourceChanged".
user890332

1
Mi sembra che fare grd.Columns(i).Width = grd.Columns(i).Widthgià funzionerà. Vedi qui .
Antonio

2
per c # simile ma con parentesi quadre dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
barlop

Potrebbe essere arrivato molto tardi, ma in qualche modo, potremmo ridimensionare in base al contenuto di una determinata riga? Diciamo, in base al contenuto delle celle nella prima riga, indipendentemente dalla larghezza delle celle nelle altre righe?
Murtuza Husain

45

Forse potresti chiamare

dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.Fill);

Dopo aver impostato l'origine dati. Imposta la larghezza e consente il ridimensionamento.

Ulteriori informazioni sul metodo DataGridView.AutoResizeColumns di MSDN (DataGridViewAutoSizeColumnsMode) .


2
Non sono sicuro del motivo per cui questa risposta non sta ottenendo più attenzione. Molto più pulito. Anche se stai cercando di abbinare la larghezza del contenuto della cella, DataGridViewAutoSizeColumnsMode.AllCells funziona un po 'meglio.
iwalkbarefoot

31
utilizzando questa soluzione ottengo il seguente errore: "Il parametro autoSizeColumnMode non è valido per questa operazione. Non può essere NotSet, None o Fill ma deve indicare un criterio di dimensionamento." . Ho finito per usare questo dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
itsho

6
L'uso di DataGridViewAutoSizeColumnMode.Fill non funziona perché ignora il contenuto della cella durante il ridimensionamento delle colonne.
Stuart Helwig

Ho usato questo metodo con DataGridViewAutoSizeColumnsMode.DisplayedCells. Inoltre, in Progettazione form, AutoSizeColumnsMode è impostato su Nessuno. Avevo bisogno di eseguire questa chiamata al metodo nel gestore di eventi DataBindingComplete di DataGridView, per assicurarmi che si (ri) ridimensionasse sempre correttamente.
Daan

7
Non capisco tutti i voti positivi ... Questo non funziona affatto, la documentazione MSDN è chiara, facendo ciò porta a un'eccezione ArgumentException se autoSizeColumnsMode ha il valore Nessuno o Fill.
Larry

31

Versione AC # del codice di 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;
}

Inserito come Community Wiki in modo da non scoraggiare la reputazione degli altri


15

Nella mia applicazione ho impostato

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

Inoltre, ho impostato l'estensione

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

Ora le larghezze delle colonne possono essere modificate e le colonne possono essere riorganizzate dall'utente. Funziona abbastanza bene per me.

Forse funzionerà per te.


L'impostazione di AutoSizeColumnsMode della griglia su "Fill" sembra impostare tutte le colonne alle stesse larghezze. Sì, le colonne sono quindi ridimensionabili ma le larghezze iniziali sono tutte sbagliate. Potrebbe essere necessario impostare le larghezze delle colonne nel codice "manualmente".
Stuart Helwig,

DV- grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumn-> s <- Mode.Fill; (ti sei perso la s, è ColumsMode sul lato sinistro e sul lato destro, quindi quella tua riga non si compila) Il codice per ottenere il dimensionamento automatico di datagridview è molto fastidioso così com'è, quindi controlla prima la tua risposta . È la prima riga che hai scritto ed è sbagliata.
barlop

@barlop grazie per la tua risposta. Hai il privilegio di modificare domande e risposte. Se noti un errore nel mio codice, sentiti libero di modificarlo.
Jehof

12

Dopo aver aggiunto i dati alla griglia, aggiungi il seguente codice che regolerà la colonna in base alla lunghezza dei dati in ciascuna cella

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

Ecco il risultato

inserisci qui la descrizione dell'immagine


9

Bene, l'ho fatto in questo modo:

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

in quell'ordine particolare. Le colonne vengono ridimensionate (estese) E l'utente può ridimensionare le colonne in seguito.


6

Se ho capito correttamente la domanda, dovrebbe esserci un modo più semplice per realizzare ciò di cui hai bisogno. Chiamata dgvSomeDataGrid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);

Questo dovrebbe fare il trucco. Tuttavia, c'è una trappola in quanto non puoi semplicemente chiamare questo metodo direttamente dopo aver popolato il tuo controllo DataGridView. Invece dovrai aggiungere un EventHandler per l'evento VisibleChanged e chiamare il metodo lì.


1
Ciò ridimensionerebbe le colonne in base al contenuto, ma non garantirebbe che tutto lo spazio disponibile sulla griglia venga utilizzato. Cioè, non "riempie" lo spazio rimanente se ce n'è.
Stuart Helwig

5

Due semplici righe di codice funzionano per me.

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

4

Riprendi la domanda:
fai in modo che la larghezza della colonna si adatti al contenuto (con un metodo diverso in tutta la colonna),
ma poi consenti all'utente di impostare la larghezza della colonna ...

Sviluppando dalla risposta di Miroslav Zadravec , per me ciò che ha funzionato è stato immediatamente utilizzare l'auto computed column.Widthper impostare ... 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

Questo viene testato per funzionare quando DataGridViewè già creato, usando un trucco come questo .


Preferisco usare un foreach come fa il tuo codice. Lo rende più leggibile quando non hai matematica all'inizio del ciclo. L'ho fatto in questo modo e "column.Width = column.Width;" è interessante.
Greg Barth

4

Questo ha fatto miracoli per me:

dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);

1
Soluzione semplice!
Mark Kram

1
Ha funzionato per me solo se impostato su Nessuno in seguito, ovverodataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
Do-do-new

3

Questo adatta automaticamente tutte le colonne in base al loro contenuto, riempie lo spazio vuoto rimanente allungando una colonna specificata e impedisce il comportamento di "salto" impostando l'ultima colonna da riempire per qualsiasi ridimensionamento futuro.

// 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;

So che è una vecchia risposta, ma funziona bene, anche quando il numero di colonne non è noto in anticipo.
Nilo Paim

2

Codice C # leggermente più ordinato dal codice di Miroslav Zadravec supponendo che tutte le colonne debbano essere ridimensionate automaticamente

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

Un'altra versione del codice di Miroslav Zadravec, ma leggermente più automatizzata e universale:

    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;
        }
    }

Metto la seconda parte in un evento separato, perché datagridvewcompilo l'inizializzazione del modulo e se entrambe le parti sono presenti, non cambia nulla, perché probabilmente l'autosize calcola le larghezze dopo che datagridviewè stato visualizzato, quindi le larghezze sono ancora predefinite nel Form1()metodo. Dopo aver terminato questo metodo, autosize fa il suo trucco e subito dopo (quando viene mostrato il form) possiamo impostare le larghezze dalla seconda parte del codice (qui Form1Shownnell'evento). Questo funziona per me come un fascino.


2

Ecco un codice semplificato per la risposta di Miroslav Zadravec in 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

Hai provato a impostare la FillWeightproprietà del tuoDataGridViewColumns oggetto?

Per esempio:

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

Penso che dovrebbe funzionare nel tuo caso.


1

Un piccolo miglioramento rispetto alla versione di 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

Le larghezze delle colonne impostate per adattarsi al suo contenuto Ho usato la seguente dichiarazione, Ha risolto il mio problema.

Primo passo :

RadGridViewName.AutoSize = true;

Secondo passo :

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

Terza fase:

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);

Questo dovrebbe funzionare sia che dataGridViewsia stato visualizzato o meno (cioè anche se chiamato dal costruttore della classe).

Lo stesso metodo, ma con DataGridViewAutoSizeColumnMode.DisplayedCells, fallisce nel caso precedente per l'ovvia ragione: nessuna cella è stata ancora visualizzata! Per qualche motivo non ovvio, AutoResizeColumnsfallisce anche in questo caso.


0

Se ad esempio leghi la tua origine dati a un datatable, devi impostare le proprietà dopo che l'associazione è terminata:

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

0
  • Grazie per la soluzione di cui sopra (per scorrere il DataGridView.Columnscambiamento AutoSizeModedi uno valido, il valore della larghezza raccogliere e impostare di nuovo dopo il cambiamento AutoSizeModediDataGridViewAutoSizeColumnMode.None ).
  • Ho lottato con esso e ho notato che non funzionerà ogni volta che viene chiamato dal costruttore della classe o da qualsiasi riga prima Form.Show()o Form.ShowDialog(). Quindi ho inserito questo snippet di codice Form.Shownnell'evento e questo funziona per me.
  • Il mio codice trasformato, indipendentemente da ciò che è stato DataGridView.AutoSizeColumnsModeimpostato prima, lo uso DataGridViewColumn.GetPreferredWidth()invece di modificare DataGridViewColumn.AutoSizeModee impostare immediatamente il valore di larghezza, quindi cambio DataGridView.AutoSizeColumnsModeuna volta:

    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;
    }
  • Assicurati di impostare

            dataGridView.AllowUserToResizeColumns = true;
  • Non so come mai funzioni solo dopo aver mostrato il modulo.


0

Ho dovuto farlo in VB e preferisco suddividerlo in un metodo che ho inserito in un modulo. È possibile aggiungere la colonna Fill come un altro parametro ByRef, se lo si desidera.

''' <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

Potresti fare qualcosa del genere:

   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;

Tutte le colonne si adatteranno al contenuto tranne l'ultima riempirà la griglia.


0

Con $ array come contenuto di un PSCustomObject, funziona:

$dataGridView1.DataSource=[collections.arraylist]($array)
$dataGridView1.Columns | Foreach-Object{$_.AutoSizeMode = [System.Windows.Forms.DataGridViewAutoSizeColumnMode]::AllCells}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.