Wie können Sie die Größe von Spalten in einem DataGridView-Steuerelement automatisch ändern UND dem Benutzer erlauben, die Größe der Spalten in demselben Raster zu ändern?

109

Ich fülle ein DataGridView-Steuerelement in einem Windows Form (C # 2.0 nicht WPF).

Mein Ziel ist es, ein Raster anzuzeigen, das die gesamte verfügbare Breite sauber mit Zellen ausfüllt - dh keine unbenutzten (dunkelgrauen) Bereiche rechts unten und jede Spalte entsprechend den darin enthaltenen Daten entsprechend dimensioniert, dem Benutzer jedoch auch die Größenänderung aller Spalten ermöglicht nach ihrem Geschmack.

Ich versuche dies zu erreichen, indem ich den AutoSizeMode jeder Spalte auf DataGridViewAutoSizeColumnMode.AllCells setze, mit Ausnahme einer der Spalten, die ich auf DataGridViewAutoSizeColumnMode.Fill gesetzt habe , um sicherzustellen, dass der gesamte Bereich des Rasters sauber mit Daten gefüllt ist. (Es macht mir nichts aus, dass der Benutzer beim Versuch, die Größe dieser Spalte zu ändern, auf eine Größe zurückspringt, die sicherstellt, dass der horizontale Raum immer verwendet wird.)

Wie bereits erwähnt, möchte ich dem Benutzer nach dem Laden erlauben, die Größe der Spalten an seine eigenen Anforderungen anzupassen. Wenn Sie diese AutoSizeMode-Werte für jede Spalte festlegen, kann der Benutzer diese Spalten anscheinend nicht ändern.

Ich habe versucht, den AutoSizeMode nicht für alle Spalten festzulegen, wodurch eine Größenänderung möglich ist, ABER die Anfangsgröße wird nicht gemäß den in den Zellen enthaltenen Daten festgelegt. Das gleiche Ergebnis tritt auf, wenn der AutoSizeMode des Rasters nach dem Laden der Daten wieder auf "Nicht festgelegt" geändert wird.

Fehlt hier eine Einstellung, die die automatische Einstellung der Standardspaltenbreiten UND der Größenänderung des Benutzers ermöglicht, oder muss ich beim Auffüllen des DataGridView-Steuerelements eine andere Technik anwenden?

Stuart Helwig
quelle
Setzen Sie es nicht auf "Nicht gesetzt". Setzen Sie es auf "Keine", damit die Größenänderung nicht zurückgesetzt wird. Zurückgeprüft für c #, .net2.0
bh_earth0

Antworten:

132

Dieser Trick funktioniert bei mir:

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

Was hier passiert, ist, dass Sie die automatische Größe auf den gewünschten Modus einstellen und dann spaltenweise die Breite speichern, die sie aus der automatischen Größenberechnung erhalten hat, die automatische Größe entfernen und die Breite auf den zuvor gespeicherten Wert einstellen.

Miroslav Zadravec
quelle
1
Ich habe ähnlichen Code in eine Routine namens AutoResizeColumnWidthsYetAllowUserResizing eingefügt. Es wird aufgerufen, nachdem das Raster anfänglich gefüllt wurde und auch nachdem der Benutzer Daten bearbeitet hat (dh aus dem CellEndEdit-Ereignis des Rasters).
DeveloperDan
5
Das ist großartiger Code. Muss in das Ereignis 'DataGridView1_DataSourceChanged' eingefügt werden.
user890332
1
Es scheint mir, dass das Tun grd.Columns(i).Width = grd.Columns(i).Widthbereits den Trick macht. Siehe hier .
Antonio
2
für c # ähnlich, aber mit eckigen Klammern dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
Barlop
Dies mag sehr spät gekommen sein, aber gibt es eine Chance oder einen Weg, die Größe basierend auf dem Inhalt einer bestimmten Zeile zu ändern? Nehmen wir an, basierend auf dem Inhalt der Zellen in der ersten Zeile, unabhängig von der Breite der Zellen in anderen Zeilen?
Murtuza Husain
45

Vielleicht könntest du anrufen

dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.Fill);

Nach dem Einstellen der Datenquelle. Dadurch wird die Breite festgelegt und die Größenänderung ermöglicht.

Weitere Informationen zur MSDN DataGridView.AutoResizeColumns-Methode (DataGridViewAutoSizeColumnsMode) .

Umair
quelle
2
Ich bin mir nicht sicher, warum diese Antwort nicht mehr Beachtung findet. Viel sauberer. Wenn Sie jedoch die Breite des Zelleninhalts anpassen möchten, funktioniert DataGridViewAutoSizeColumnsMode.AllCells etwas besser.
Iwalkbarefoot
31
Bei Verwendung dieser Lösung wird der nächste Fehler angezeigt : "Der Parameter autoSizeColumnMode ist für diesen Vorgang nicht gültig. Er kann nicht NotSet, None oder Fill sein, muss jedoch ein Größenkriterium angeben." . Am
Itsho
6
Die Verwendung von DataGridViewAutoSizeColumnMode.Fill funktioniert nicht, da der Zelleninhalt bei der Größenänderung von Spalten ignoriert wird.
Stuart Helwig
Ich habe diese Methode mit verwendet DataGridViewAutoSizeColumnsMode.DisplayedCells. Darüber hinaus ist im Forms Designer der AutoSizeColumnsMode auf None festgelegt. Ich musste diesen Methodenaufruf im DataBindingComplete-Ereignishandler von DataGridView ausführen, um sicherzustellen, dass die Größe immer richtig ist.
Daan
7
Ich verstehe nicht alle Upvotes ... Dies funktioniert überhaupt nicht, die MSDN-Dokumentation ist klar. Dies führt zu einer ArgumentException, wenn der autoSizeColumnsMode den Wert None oder Fill hat.
Larry
31

AC # -Version von Miroslav Zadravecs Code

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

Gepostet als Community-Wiki, um den Ruf anderer nicht zu beeinträchtigen

Tom Kidd
quelle
15

In meiner Bewerbung habe ich eingestellt

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

Auch ich habe das eingestellt

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

Jetzt können die Spaltenbreiten geändert und die Spalten vom Benutzer neu angeordnet werden. Das funktioniert ziemlich gut für mich.

Vielleicht funktioniert das für Sie.

Jehof
quelle
Wenn Sie den AutoSizeColumnsMode des Rasters auf "Füllen" setzen, werden anscheinend alle Spalten auf die gleiche Breite eingestellt. Ja, die Spalten können dann in der Größe geändert werden, aber die anfänglichen Breiten sind alle falsch. Möglicherweise muss ich die Spaltenbreiten im Code "manuell" einstellen.
Stuart Helwig
DV- grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumn-> s <- Mode.Fill; (Sie haben das s verpasst, es ist ColumsMode auf der linken und rechten Seite, sodass Ihre Zeile nicht kompiliert wird.) Der Code, mit dem die Datagrid-Ansicht automatisch angepasst werden kann, ist sehr ärgerlich. Überprüfen Sie daher zuerst Ihre Antwort . Es ist die allererste Zeile, die Sie geschrieben haben und die falsch ist.
Barlop
@barlop danke für deine Antwort. Sie haben das Recht, Fragen und Antworten zu bearbeiten. Wenn Sie einen Fehler in meinem Code entdecken, können Sie ihn jederzeit bearbeiten.
Jehof
12

Fügen Sie nach dem Hinzufügen der Daten zum Raster den folgenden Code hinzu, der die Spalte entsprechend der Datenlänge in jeder Zelle anpasst

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

Hier ist das Ergebnis

Geben Sie hier die Bildbeschreibung ein

Sarath Avanavu
quelle
9

Nun, ich habe das so gemacht:

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

in dieser bestimmten Reihenfolge. Die Größe der Spalten wird geändert (erweitert) UND der Benutzer kann die Größe der Spalten anschließend ändern.

mpss
quelle
6

Wenn ich die Frage richtig verstanden habe, sollte es einen einfacheren Weg geben, das zu erreichen, was Sie brauchen. Anruf dgvSomeDataGrid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);

Das sollte den Trick machen. Es gibt jedoch eine Gefahr, da Sie diese Methode nicht einfach direkt nach dem Auffüllen Ihres DataGridView-Steuerelements aufrufen können. Stattdessen müssen Sie einen EventHandler für das VisibleChanged-Ereignis hinzufügen und die Methode dort aufrufen.

Gorgsenegger
quelle
1
Dies würde die Größe der Spalten entsprechend dem Inhalt ändern, jedoch nicht sicherstellen, dass der gesamte verfügbare Rasterplatz genutzt wird. Dh "füllt" den verbleibenden Raum nicht aus, wenn es einen gibt.
Stuart Helwig
5

Ein einfacher Codecode funktioniert für mich.

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

Fortsetzung der Frage:
Lassen Sie die Spaltenbreite an den Inhalt anpassen (mit unterschiedlichen Methoden in der Spalte),
aber erlauben Sie dem Benutzer dann, die Spaltenbreite festzulegen ...

Ausgehend von Miroslav Zadravecs Antwort funktionierte für mich sofort die Verwendung des automatisch berechneten column.WidthSatzes ... 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

Dies wird auf der Arbeit getestet , wenn die DataGridViewbereits erstellt wird, einen Trick , wie mit dieser .

Antonio
quelle
Ich bevorzuge die Verwendung eines foreach wie Ihr Code. Es macht es besser lesbar, wenn Sie keine Mathematik oben in der Schleife haben. Ich habe es so gemacht und die "column.Width = column.Width;" ist interessant.
Greg Barth
4

Das hat Wunder für mich bewirkt:

dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
Vaishali
quelle
1
Einfache Lösung!
Mark Kram
1
Arbeitete nur für mich, wenn danach keine gesetzt wurde, dhdataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
Do-do-new
3

Dadurch werden alle Spalten entsprechend ihrem Inhalt automatisch angepasst, der verbleibende leere Bereich durch Dehnen einer angegebenen Spalte ausgefüllt und das Sprungverhalten verhindert, indem die letzte Spalte festgelegt wird, die für zukünftige Größenänderungen gefüllt werden soll.

// 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
quelle
Ich weiß, dass es eine alte Antwort ist, aber ich arbeite gut, auch wenn die Anzahl der Spalten nicht im Voraus bekannt ist.
Nilo Paim
2

Etwas übersichtlicherer C # -Code aus Miroslav Zadravecs Code, vorausgesetzt, alle Spalten müssen automatisch angepasst werden

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;
}
rauben
quelle
2

Eine andere Version von Miroslav Zadravecs Code, aber etwas automatisierter und universeller:

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

Ich habe den zweiten Teil in ein separates Ereignis datagridveweingefügt , da ich die Initialisierung des Formulars ausfülle und wenn beide Teile vorhanden sind, ändert sich nichts, da die automatische Größe wahrscheinlich die Breite berechnet, nachdem sie datagridviewangezeigt wurde, sodass die Breite in der Form1()Methode immer noch Standard ist. Nach Abschluss dieser Methode macht die automatische Größe ihren Trick und unmittelbar danach (wenn das Formular angezeigt wird) können wir die Breiten nach dem zweiten Teil des Codes festlegen (hier für den Form1ShownFall). Das funktioniert für mich wie ein Zauber.

LQd
quelle
2

Hier ist ein vereinfachter Code für Miroslav Zadravecs Antwort 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;
Cassio Accioly
quelle
1

Haben Sie versucht, die FillWeightEigenschaft Ihres DataGridViewColumnsObjekts einzurichten ?

Beispielsweise:

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

Ich denke, es sollte in Ihrem Fall funktionieren.

Aleksei Rubanovskii
quelle
1

Eine kleine Verbesserung gegenüber Schnapples Version

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
quelle
1

dataGridView1.AutoResizeColumns ();

Nick Andriopoulos
quelle
1

Die Spaltenbreiten wurden so eingestellt, dass sie zum Inhalt passen. Ich habe die folgende Anweisung verwendet. Sie hat mein Problem behoben.

Erster Schritt :

RadGridViewName.AutoSize = true;

Zweiter Schritt :

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

Dritter Schritt :

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

Dies sollte funktionieren, unabhängig davon, ob das dataGridViewangezeigt wurde oder nicht (dh auch wenn es vom Klassenkonstruktor aufgerufen wird).

Die gleiche Methode, jedoch mit DataGridViewAutoSizeColumnMode.DisplayedCells, schlägt im obigen Fall aus dem offensichtlichen Grund fehl - es wurde noch keine Zelle angezeigt! Aus irgendeinem nicht offensichtlichen Grund AutoResizeColumnsschlägt dies auch in diesem Fall fehl.

Unvergängliche Nacht
quelle
0

Wenn Sie Ihre Datenquelle beispielsweise an eine Datentabelle binden, müssen Sie die Eigenschaften nach Abschluss der Bindung festlegen:

        private void dgv_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
            dgv.AutoResizeColumns();
            dgv.AllowUserToResizeColumns = true;
        }
ehh
quelle
0
  • Vielen Dank für die obige Lösung (Um das zu durchlaufen DataGridView.Columns, wechseln Sie AutoSizeModezu einem gültigen, sammeln Sie den Breitenwert und setzen Sie ihn nach der Änderung AutoSizeModeauf zurück DataGridViewAutoSizeColumnMode.None).
  • Ich kämpfte damit und bemerkte, dass es nicht funktioniert, wenn es vom Klassenkonstruktor oder einer Zeile vor Form.Show()oder aufgerufen wird Form.ShowDialog(). Also habe ich dieses Code-Snippet in das Form.ShownEvent eingefügt und das funktioniert für mich.
  • Mein transformierter Code, unabhängig von DataGridView.AutoSizeColumnsModeden zuvor festgelegten, verwende ich, DataGridViewColumn.GetPreferredWidth()anstatt den Breitenwert DataGridViewColumn.AutoSizeModesofort zu ändern und festzulegen , und ändere ihn dann DataGridView.AutoSizeColumnsModeeinmal:

    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;
    }
  • Stellen Sie sicher, dass Sie einstellen

            dataGridView.AllowUserToResizeColumns = true;
  • Ich weiß nicht, warum das erst funktioniert, nachdem das Formular angezeigt wurde.

user1779049
quelle
0

Ich musste dies in VB tun und es vorziehen, es auf eine Methode aufzuteilen, die ich in ein Modul eingefügt habe. Falls gewünscht, können Sie die Spalte Füllen als weiteren ByRef-Parameter hinzufügen.

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

Sie könnten so etwas tun:

   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;

Alle Spalten werden an den Inhalt angepasst, mit Ausnahme der letzten, die das Raster ausfüllt.

usr4217
quelle
0

Mit $ array als Inhalt eines PSCustomObject funktioniert dies:

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