Jak automatycznie zmienić rozmiar kolumn w kontrolce DataGridView ORAZ umożliwić użytkownikowi zmianę rozmiaru kolumn w tej samej siatce?

109

Wypełniam formant DataGridView w formularzu systemu Windows (C # 2,0 nie WPF).

Moim celem jest wyświetlenie siatki, która starannie wypełnia całą dostępną szerokość komórkami - tj. Żadnych nieużywanych (ciemnoszarych) obszarów po prawej stronie i odpowiednio dopasowuje rozmiar każdej kolumny zgodnie z zawartymi w niej danymi, ale także umożliwia użytkownikowi zmianę rozmiaru dowolnej kolumny według ich upodobań.

Próbuję to osiągnąć, ustawiając AutoSizeMode każdej kolumny na DataGridViewAutoSizeColumnMode.AllCells, z wyjątkiem jednej z kolumn, które ustawiłem na DataGridViewAutoSizeColumnMode.Fill , aby upewnić się, że cały obszar siatki jest starannie wypełniony danymi. (Nie mam nic przeciwko temu, że gdy użytkownik próbuje zmienić rozmiar tej kolumny, wraca do rozmiaru, który zapewnia, że ​​przestrzeń pozioma jest zawsze używana.)

Jednak, jak wspomniałem, po załadowaniu chciałbym pozwolić użytkownikowi na zmianę rozmiaru kolumn, aby dopasować je do własnych wymagań - ustawiając te wartości AutoSizeMode dla każdej kolumny, wydaje się, że użytkownik nie może wtedy zmienić rozmiaru tych kolumn.

Próbowałem nie ustawiać AutoSizeMode wszystkich kolumn, co pozwala na zmianę rozmiaru, ALE nie ustawia rozmiaru początkowego zgodnie z danymi, które zawierają komórki. Ten sam wynik występuje w przypadku zmiany AutoSizeMode siatki z powrotem na „Not Set” po załadowaniu danych.

Czy brakuje mi ustawienia, które umożliwia automatyczne ustawianie domyślnych szerokości kolumn ORAZ zmianę rozmiaru użytkownika, czy też istnieje inna technika, której muszę użyć podczas wypełniania kontrolki DataGridView?

Stuart Helwig
źródło
nie ustawiaj go na „Not Set” ustaw go na „None”, aby zmiana rozmiaru nie została przywrócona - testowane dla c #,
.net2.0

Odpowiedzi:

132

Ta sztuczka działa dla mnie:

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

To, co się tutaj dzieje, polega na tym, że ustawiasz autodopasowanie na dowolny tryb, którego potrzebujesz, a następnie kolumna po kolumnie przechowujesz szerokość uzyskaną z automatycznego obliczania rozmiaru, usuwasz automatyczne dostosowywanie i ustawiasz szerokość na wartość, którą wcześniej zapisałeś.

Miroslav Zadravec
źródło
1
Podobny kod umieściłem w procedurze o nazwie AutoResizeColumnWidthsYetAllowUserResizing. Jest wywoływana po początkowym wypełnieniu siatki, a także po edycji danych przez użytkownika (czyli ze zdarzenia CellEndEdit siatki).
DeweloperDan
5
To świetny kod. Należy umieścić w zdarzeniu „DataGridView1_DataSourceChanged”.
user890332
1
Wydaje mi się, że robienie grd.Columns(i).Width = grd.Columns(i).Widthjuż wystarczy. Zobacz tutaj .
Antonio,
2
dla c # podobny, ale z nawiasami kwadratowymi dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
barlop
Mogło to nastąpić bardzo późno, ale jest jakaś szansa lub sposób, aby zmienić rozmiar na podstawie zawartości określonego wiersza? Powiedzmy, na podstawie zawartości komórek w pierwszym wierszu, niezależnie od szerokości komórek w innych wierszach?
Murtuza Husain
45

Może mógłbyś zadzwonić

dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.Fill);

Po ustawieniu źródła danych. Ustawi szerokość i pozwoli na zmianę rozmiaru.

Więcej o metodzie MSDN DataGridView.AutoResizeColumns (DataGridViewAutoSizeColumnsMode) .

Umair
źródło
2
Nie jestem pewien, dlaczego ta odpowiedź nie przyciąga więcej uwagi. Dużo czystsze. Chociaż jeśli chcesz dopasować szerokość zawartości komórki, DataGridViewAutoSizeColumnsMode.AllCells działa nieco lepiej.
iwalkbarefoot
31
Korzystając z tego rozwiązania, otrzymuję następny błąd: „Parametr autoSizeColumnMode nie jest prawidłowy dla tej operacji. Nie może to być NotSet, None lub Fill, ale musi wskazywać kryteria rozmiaru.” . Skończyło się na użyciu tego dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
itsho
6
Korzystanie z DataGridViewAutoSizeColumnMode.Fill nie działa, ponieważ ignoruje zawartość komórki podczas określania rozmiaru kolumn.
Stuart Helwig
Użyłem tej metody z DataGridViewAutoSizeColumnsMode.DisplayedCells. Ponadto w Projektancie formularzy AutoSizeColumnsMode jest ustawiona na None. Musiałem wykonać to wywołanie metody w programie obsługi zdarzeń DataBindingComplete w DataGridView, aby upewnić się, że zawsze (ponownie) rozmiary są prawidłowe.
Daan
7
Nie rozumiem wszystkich upvotes ... To w ogóle nie działa, dokumentacja MSDN jest jasna, prowadzi to do ArgumentException, jeśli autoSizeColumnsMode ma wartość None lub Fill.
Larry,
31

Wersja AC # kodu Miroslava Zadraveca

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

Opublikowane jako Wiki społeczności, aby nie osłabiać reputacji innych

Tom Kidd
źródło
15

W mojej aplikacji ustawiłem

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

Ustawiłem również

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

Teraz można zmieniać szerokości kolumn i przestawiać kolumny przez użytkownika. U mnie to działa całkiem nieźle.

Może to zadziała dla Ciebie.

Jehof
źródło
Ustawienie AutoSizeColumnsMode siatki na „Fill” wydaje się ustawiać wszystkie kolumny na tę samą szerokość. Tak, rozmiary kolumn można następnie zmienić, ale początkowe szerokości są nieprawidłowe. Być może trzeba będzie ustawić szerokości kolumn w kodzie „ręcznie”.
Stuart Helwig
DV- grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumn-> s <- Mode.Fill; (przegapiłeś s, to ColumsMode po lewej i prawej stronie, więc ta twoja linia się nie kompiluje) Kod, który sprawi, że datagridview zostanie automatycznie dostosowany, jest bardzo irytujący, więc przynajmniej sprawdź najpierw swoją odpowiedź . To pierwsza linia, którą napisałeś i jest błędna.
barlop
@barlop dzięki za twoją odpowiedź. Masz przywilej edycji pytań i odpowiedzi. Jeśli zauważysz błąd w moim kodzie, możesz go edytować.
Jehof
12

Po dodaniu danych do siatki dodaj poniższy kod, który dostosuje kolumnę zgodnie z długością danych w każdej komórce

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

Oto wynik

wprowadź opis obrazu tutaj

Sarath Avanavu
źródło
9

Cóż, zrobiłem to tak:

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

w tej kolejności. Rozmiar kolumn jest zmieniany (rozszerzany) ORAZ użytkownik może później zmienić rozmiar kolumn.

mps
źródło
6

Jeśli dobrze zrozumiałem pytanie, powinien być łatwiejszy sposób na osiągnięcie tego, czego potrzebujesz. Połączenie dgvSomeDataGrid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);

To powinno załatwić sprawę. Istnieje jednak jedna pułapka, ponieważ nie można po prostu wywołać tej metody bezpośrednio po wypełnieniu kontrolki DataGridView. Zamiast tego będziesz musiał dodać EventHandler dla zdarzenia VisibleChanged i wywołać tam metodę.

Gorgsenegger
źródło
1
To zmieniłoby rozmiar kolumn w zależności od zawartości, ale nie zapewniłoby wykorzystania całej dostępnej przestrzeni siatki. To znaczy, nie „wypełnia” pozostałej przestrzeni, jeśli taka istnieje.
Stuart Helwig
5

U mnie działają proste dwie linie kodu.

dataGridView.DataSource = dataTable;
dataGridView.AutoResizeColumns();
Rashmin Javiya
źródło
4

Wznów pytanie:
dostosuj szerokość kolumny do treści (inną metodą w całej kolumnie),
ale następnie pozwól użytkownikowi ustawić szerokość kolumny ...

Rozwijanie od odpowiedzi Miroslav Zadravec jest dla mnie to, co działało natychmiast za pomocą automatycznego komputerowej column.Widthdo zestawu ... 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

To jest testowany do pracy, gdy DataGridViewjest już utworzony, stosując trick jak ten .

Antonio
źródło
Wolę używać foreach tak, jak robi to twój kod. Dzięki temu jest bardziej czytelny, gdy na początku pętli nie ma żadnej matematyki. Zrobiłem to w ten sposób, a „column.Width = column.Width;” jest interesujący.
Greg Barth
4

Zrobiło to dla mnie cuda:

dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
Vaishali
źródło
1
Proste rozwiązanie!
Mark Kram,
1
Działało dla mnie tylko wtedy, gdy zostało ustawione na None później, tj.dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
Do-z-z-new
3

Spowoduje to automatyczne dopasowanie wszystkich kolumn zgodnie z ich zawartością, wypełnienie pozostałej pustej przestrzeni przez rozciągnięcie określonej kolumny i zapobiegnie zachowaniu „przeskakiwania”, ustawiając ostatnią kolumnę do wypełnienia w celu przyszłej zmiany rozmiaru.

// 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
źródło
Wiem, że to stara odpowiedź, ale ładnie działa, nawet jeśli liczba kolumn nie jest z góry znana.
Nilo Paim
2

Nieco schludniejszy kod C # z kodu Miroslava Zadraveca, przy założeniu, że wszystkie kolumny mają być automatycznie zmieniane

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;
}
Obrabować
źródło
2

Kolejna wersja kodu Miroslava Zadraveca, ale nieco bardziej zautomatyzowana i uniwersalna:

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

Drugą część umieszczam w osobnym zdarzeniu, ponieważ wypełniam datagridvewinicjalizację formularza i jeśli są obie części to nic się nie zmienia, ponieważ prawdopodobnie autosize oblicza szerokości po datagridviewwyświetleniu, więc szerokości są nadal domyślne w Form1()metodzie. Po skończeniu tej metody autosize robi swoje i zaraz po tym (po wyświetleniu formularza) możemy ustawić szerokości według drugiej części kodu (tutaj w Form1Shownprzypadku). To działa na mnie jak urok.

LQd
źródło
2

Oto uproszczony kod odpowiedzi Miroslava Zadraveca w języku 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
źródło
1

Czy próbowałeś ustawić FillWeightwłasność swojegoDataGridViewColumns obiektu?

Na przykład:

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

Myślę, że to powinno działać w twoim przypadku.

Aleksei Rubanovskii
źródło
1

Małe ulepszenie w stosunku do wersji 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
źródło
1

dataGridView1.AutoResizeColumns ();

Nick Andriopoulos
źródło
1

Szerokości kolumn ustawione tak, aby pasowały do ​​jej zawartości, użyłem poniższego stwierdzenia: To rozwiązało mój problem.

Pierwszy krok :

RadGridViewName.AutoSize = true;

Drugi krok :

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

Trzeci krok :

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
źródło
1
foreach (DataGridViewColumn c in dataGridView.Columns)
    c.Width = c.GetPreferredWidth(DataGridViewAutoSizeColumnMode.AllCells, true);

Powinno to działać niezależnie od tego, czy dataGridViewzostał wyświetlony, czy nie (tj. Nawet jeśli został wywołany z konstruktora klasy).

Ta sama metoda, ale z DataGridViewAutoSizeColumnMode.DisplayedCells, zawodzi w powyższym przypadku z oczywistego powodu - żadna komórka nie została jeszcze wyświetlona! Z jakiegoś nieoczywistego powodu AutoResizeColumnsrównież zawodzi w tym przypadku.

Niezniszczalna noc
źródło
0

Jeśli na przykład powiążesz swoje źródło danych z plikiem danych, musisz ustawić właściwości po wykonaniu powiązania:

        private void dgv_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
            dgv.AutoResizeColumns();
            dgv.AllowUserToResizeColumns = true;
        }
ehh
źródło
0
  • Dzięki za powyższe rozwiązanie ( aby wykonać iterację DataGridView.Columns, zmień AutoSizeModena prawidłową, zbierz wartość szerokości i ustaw ją ponownie po zmianie AutoSizeModenaDataGridViewAutoSizeColumnMode.None ).
  • Zmagałem się z tym i zauważyłem, że nie zadziała, jeśli zostanie wywołany z konstruktora klasy lub dowolnej linii przed Form.Show()lub Form.ShowDialog(). Więc umieściłem ten fragment kodu w Form.Shownzdarzeniu i to działa dla mnie.
  • Mój przekształcony kod, niezależnie od tego, co DataGridView.AutoSizeColumnsModeustawiono wcześniej, używam DataGridViewColumn.GetPreferredWidth()zamiast zmieniać DataGridViewColumn.AutoSizeModei natychmiast ustawiam wartość szerokości, a potem zmieniam DataGridView.AutoSizeColumnsModeraz:

    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;
    }
  • Pamiętaj, aby ustawić

            dataGridView.AllowUserToResizeColumns = true;
  • Nie wiem, dlaczego to działa dopiero po wyświetleniu formularza.

user1779049
źródło
0

Musiałem to zrobić w VB i wolę podzielić to na metodę, którą umieściłem w Module. W razie potrzeby możesz dodać kolumnę Fill jako kolejny parametr ByRef.

''' <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
źródło
0

Możesz zrobić coś takiego:

   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;

Wszystkie kolumny dostosują się do treści, z wyjątkiem ostatniej, która wypełni siatkę.

usr4217
źródło
0

Gdy $ array jest zawartością PSCustomObject, działa to:

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