¿Cómo cambia automáticamente el tamaño de las columnas en un control DataGridView Y permite al usuario cambiar el tamaño de las columnas en esa misma cuadrícula?

109

Estoy completando un control DataGridView en un formulario de Windows (C # 2.0 no WPF).

Mi objetivo es mostrar una cuadrícula que llene cuidadosamente todo el ancho disponible con celdas, es decir, que no haya áreas no utilizadas (gris oscuro) en la parte derecha y el tamaño de cada columna de acuerdo con los datos que contiene, pero también permite al usuario cambiar el tamaño de cualquiera de las columnas. a su gusto.

Estoy intentando lograr esto configurando el AutoSizeMode de cada columna para que sea DataGridViewAutoSizeColumnMode.AllCells, excepto una de las columnas que configuré en DataGridViewAutoSizeColumnMode.Fill para asegurar que toda el área de la cuadrícula esté perfectamente llena de datos. (No me importa que cuando el usuario intenta cambiar el tamaño de esta columna, vuelve a un tamaño que garantiza que siempre se use el espacio horizontal).

Sin embargo, como mencioné, una vez cargada, me gustaría permitir que el usuario cambie el tamaño de las columnas para que se adapten a sus propios requisitos; al establecer estos valores de AutoSizeMode para cada columna, parece que el usuario no puede cambiar el tamaño de esas columnas.

Intenté no configurar AutoSizeMode de todas las columnas, lo que permite cambiar el tamaño, PERO no establece el tamaño inicial de acuerdo con los datos que contienen las celdas. El mismo resultado ocurre cuando se cambia el AutoSizeMode de la cuadrícula a "No establecido" después de cargar los datos.

¿Hay una configuración que me falta aquí que permita la configuración automática de los anchos de columna predeterminados Y el cambio de tamaño del usuario o hay otra técnica que debo usar al completar el control DataGridView?

Stuart Helwig
fuente
¡No otra vez en "no ajustada" ponerlo en "Ninguno" por lo resizement no volverá de nuevo - la prueba de C #, .net2.0
bh_earth0

Respuestas:

132

Este truco funciona para mí:

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

Lo que sucede aquí es que establece el tamaño automático en el modo que necesite y luego, columna por columna, almacena el ancho que obtuvo del cálculo del tamaño automático, elimina el tamaño automático y establece el ancho en el valor que almacenó antes.

Miroslav Zadravec
fuente
1
Puse un código similar en una rutina llamada AutoResizeColumnWidthsYetAllowUserResizing. Se llama después de que la cuadrícula se llena inicialmente y también después de que el usuario edita los datos (es decir, del evento CellEndEdit de la cuadrícula).
DeveloperDan
5
Este es un gran código. Debe colocarse en el evento 'DataGridView1_DataSourceChanged'.
user890332
1
Me parece que hacerlo grd.Columns(i).Width = grd.Columns(i).Widthya funcionará. Vea aquí .
Antonio
2
para c # similar pero con corchetes dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
barlop
Esto podría haber llegado muy tarde, pero ¿alguna posibilidad o forma de cambiar el tamaño en función del contenido de una fila en particular? Digamos, basado en el contenido de las celdas en la Primera Fila, independientemente del ancho de las celdas en otras filas.
Murtuza Husain
45

Tal vez podrías llamar

dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.Fill);

Después de configurar la fuente de datos. Establecerá el ancho y permitirá cambiar el tamaño.

Más sobre el método DataGridView.AutoResizeColumns de MSDN (DataGridViewAutoSizeColumnsMode) .

Umair
fuente
2
No estoy seguro de por qué esta respuesta no recibe más atención. Mucho más limpio. Aunque si está buscando hacer coincidir el ancho del contenido de la celda, DataGridViewAutoSizeColumnsMode.AllCells funciona un poco mejor.
iwalkbarefoot
31
al usar esta solución , obtengo el siguiente error: "El parámetro autoSizeColumnMode no es válido para esta operación. No puede ser NotSet, None o Fill, pero debe indicar un criterio de tamaño". . Terminé usando este dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
itsho
6
El uso de DataGridViewAutoSizeColumnMode.Fill no funciona porque ignora el contenido de la celda al dimensionar las columnas.
Stuart Helwig
He usado este método con DataGridViewAutoSizeColumnsMode.DisplayedCells. Además, en el Diseñador de formularios, AutoSizeColumnsMode se establece en Ninguno. Necesitaba ejecutar esta llamada al método en el controlador de eventos DataBindingComplete de DataGridView, para asegurarme de que siempre (re) dimensione correctamente.
Daan
7
No entiendo todos los votos a favor ... Esto no funciona en absoluto, la documentación de MSDN es clara, hacer esto conduce a una ArgumentException si autoSizeColumnsMode tiene el valor None o Fill.
Larry
31

Versión AC # del código 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;
}

Publicado como Wiki de la comunidad para no burlarse de la reputación de los demás

Tom Kidd
fuente
15

En mi aplicación he configurado

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

Además, he configurado el

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

Ahora el ancho de las columnas se puede cambiar y el usuario puede reorganizarlas. Eso funciona bastante bien para mí.

Quizás eso funcione para ti.

Jehof
fuente
Establecer el AutoSizeColumnsMode de la cuadrícula en "Fill" parece establecer todas las columnas en el mismo ancho. Sí, las columnas se pueden cambiar de tamaño, pero los anchos iniciales son incorrectos. Es posible que deba establecer los anchos de columna en el código "manualmente".
Stuart Helwig
DV- grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumn-> s <- Mode.Fill; (te perdiste el s, es ColumsMode en el lado izquierdo y en el lado derecho, por lo que esa línea tuya no se compila) El código para hacer que datagridview aumente el tamaño es muy molesto, así que al menos verifica tu respuesta primero . Es la primera línea que escribiste y está mal.
barlop
@barlop gracias por tu respuesta. Tiene el privilegio de editar preguntas y respuestas. Si detecta un error en mi código, no dude en editarlo.
Jehof
12

Después de agregar los datos a la cuadrícula, agregue el siguiente código que ajustará la columna de acuerdo con la longitud de los datos en cada celda

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

Aquí está el resultado

ingrese la descripción de la imagen aquí

Sarath Avanavu
fuente
9

Bueno, hice esto así:

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

en ese orden en particular. Las columnas cambian de tamaño (extendidas) Y el usuario puede cambiar el tamaño de las columnas posteriormente.

mpss
fuente
6

Si entendí la pregunta correctamente, debería haber una manera más fácil de lograr lo que necesita. Llamada dgvSomeDataGrid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);

Eso debería hacer el truco. Sin embargo, existe un problema, ya que no puede simplemente llamar a este método directamente después de completar su control DataGridView. En su lugar, tendrá que agregar un EventHandler para el evento VisibleChanged y llamar al método allí.

Gorgsenegger
fuente
1
Eso cambiaría el tamaño de las columnas de acuerdo con el contenido, pero no garantizaría que se use todo el espacio de cuadrícula disponible. Es decir, no "llena" el espacio restante si lo hay.
Stuart Helwig
5

Un simple dos líneas de código me funciona.

dataGridView.DataSource = dataTable;
dataGridView.AutoResizeColumns();
Rashmin Javiya
fuente
4

Resumen de la pregunta:
haga que el ancho de la columna se adapte al contenido (con un método diferente en la columna),
pero luego permita que el usuario establezca el ancho de la columna ...

¡Desarrollando a partir de la respuesta de Miroslav Zadravec , para mí lo que funcionó fue usar inmediatamente el auto calculado column.Widthpara configurar ... 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

Esto se prueba para que funcione cuando DataGridViewya está creado, usando un truco como este .

Antonio
fuente
Prefiero usar un foreach como lo hace su código. Lo hace más legible cuando no tiene ninguna matemática en la parte superior del ciclo. Lo hice de esa manera, y el "column.Width = column.Width;" es interesante.
Greg Barth
4

Esto hizo maravillas para mí:

dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
Vaishali
fuente
1
¡Solución simple!
Mark Kram
1
Funcionó para mí solo si se establece en Ninguno después, es decirdataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
Do-do-new
3

Esto ajusta automáticamente todas las columnas de acuerdo con su contenido, llena el espacio vacío restante estirando una columna específica y evita el comportamiento de "salto" configurando la última columna para que se llene para cualquier cambio de tamaño 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;
wnutt
fuente
Sé que es una respuesta antigua, pero funciona muy bien, incluso cuando no se conoce el número de columnas de antemano.
Nilo Paim
2

Código C # ligeramente más ordenado del código de Miroslav Zadravec asumiendo que todas las columnas deben tener un tamaño automático

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;
}
Robar
fuente
2

Otra versión del código de Miroslav Zadravec, pero un poco más automatizada y universal:

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

Puse la segunda parte en un evento separado, porque completé la datagridvewinicialización del formulario y si ambas partes están allí, no cambiará nada, porque probablemente el tamaño automático calcula los anchos después de que datagridviewse muestra, por lo que los anchos siguen siendo los predeterminados en el Form1()método. Después de terminar este método, el tamaño automático hace su truco e inmediatamente después de eso (cuando se muestra el formulario) podemos establecer los anchos por la segunda parte del código (aquí en el Form1Shownevento). Esto me está funcionando a las mil maravillas.

LQd
fuente
2

Aquí hay un código simplificado para la respuesta 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;
Cassio Accioly
fuente
1

¿Intentó configurar la FillWeightpropiedad de suDataGridViewColumns objeto?

Por ejemplo:

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

Creo que debería funcionar en tu caso.

Aleksei Rubanovskii
fuente
1

Una pequeña mejora de la versión 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;
}
Initrof
fuente
1

dataGridView1.AutoResizeColumns ();

Nick Andriopoulos
fuente
1

Los anchos de columna configurados para adaptarse a su contenido He usado la siguiente declaración, resolvió mi problema.

Primer paso :

RadGridViewName.AutoSize = true;

Segundo paso :

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

Tercer paso :

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; 
}
Priyanka
fuente
1
foreach (DataGridViewColumn c in dataGridView.Columns)
    c.Width = c.GetPreferredWidth(DataGridViewAutoSizeColumnMode.AllCells, true);

Esto debería funcionar si dataGridViewse ha mostrado o no (es decir, incluso si se llama desde el constructor de la clase).

El mismo método, pero con DataGridViewAutoSizeColumnMode.DisplayedCells, falla en el caso anterior por la razón obvia: ¡aún no se ha mostrado ninguna celda! Por alguna razón no obvia, AutoResizeColumnstambién falla en este caso.

Noche imperecedera
fuente
0

Si vincula su fuente de datos a una tabla de datos, por ejemplo, debe establecer las propiedades después de que finalice el enlace:

        private void dgv_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
            dgv.AutoResizeColumns();
            dgv.AllowUserToResizeColumns = true;
        }
ehh
fuente
0
  • Gracias por la solución anterior (para recorrer en iteración DataGridView.Columns, cambie AutoSizeModea uno válido, recopile el valor de ancho y vuelva a configurarlo después del cambio AutoSizeModeaDataGridViewAutoSizeColumnMode.None ).
  • Luché con él y noté que no funcionará cada vez que se llame desde el constructor de la clase o cualquier línea antes Form.Show()o Form.ShowDialog(). Así que puse este fragmento de código en el Form.Shownevento y esto me funciona.
  • Mi código transformado, independientemente de lo que haya DataGridView.AutoSizeColumnsModeconfigurado antes, lo uso en DataGridViewColumn.GetPreferredWidth()lugar de cambiar DataGridViewColumn.AutoSizeModey establecer el valor de ancho de inmediato, luego lo cambio DataGridView.AutoSizeColumnsModeuna vez:

    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;
    }
  • Asegúrate de configurar

            dataGridView.AllowUserToResizeColumns = true;
  • No sé cómo es que esto solo funciona después de que se muestra el formulario.

usuario1779049
fuente
0

Tuve que hacer esto en VB y prefiero dividirlo en un método que coloqué en un Módulo. Puede agregar la columna Relleno como otro parámetro ByRef si lo desea.

''' <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
Greg Barth
fuente
0

Podrías hacer algo como esto:

   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;

Todas las columnas se adaptarán al contenido excepto la última que llenará la cuadrícula.

usr4217
fuente
0

Con $ array siendo el contenido de un PSCustomObject, esto funciona:

$dataGridView1.DataSource=[collections.arraylist]($array)
$dataGridView1.Columns | Foreach-Object{$_.AutoSizeMode = [System.Windows.Forms.DataGridViewAutoSizeColumnMode]::AllCells}
wtcunningham
fuente