Как вы автоматически изменяете размер столбцов в элементе управления DataGridView И позволяете пользователю изменять размер столбцов в той же сетке?

109

Я заполняю элемент управления DataGridView в форме Windows (C # 2.0, а не WPF).

Моя цель - отобразить сетку, которая аккуратно заполняет всю доступную ширину ячейками, то есть без неиспользуемых (темно-серых) областей справа и размер каждого столбца в соответствии с данными, которые он содержит, но также позволяет пользователю изменять размер любого из столбцов по своему вкусу.

Я пытаюсь добиться этого, задав для AutoSizeMode каждого столбца значение DataGridViewAutoSizeColumnMode.AllCells, за исключением одного из столбцов, для которого я установил значение DataGridViewAutoSizeColumnMode.Fill , чтобы вся область сетки была аккуратно заполнена данными. (Я не возражаю, когда пользователь пытается изменить размер этого столбца, он возвращается к размеру, который гарантирует, что горизонтальное пространство всегда используется.)

Однако, как я уже упоминал, после загрузки я хотел бы разрешить пользователю изменять размер столбцов в соответствии со своими требованиями - при установке этих значений AutoSizeMode для каждого столбца кажется, что пользователь не может затем изменить размер этих столбцов.

Я пытался не устанавливать AutoSizeMode для всех столбцов, который позволяет изменять размер, НО не устанавливает начальный размер в соответствии с данными, содержащимися в ячейках. Тот же результат происходит при изменении AutoSizeMode сетки обратно на «Not Set» после загрузки данных.

Есть ли параметр, который мне здесь не хватает, который позволяет автоматически устанавливать ширину столбцов по умолчанию и изменять размер пользователя, или есть другой метод, который я должен использовать при заполнении элемента управления DataGridView?

Стюарт Хельвиг
источник
не устанавливайте для него значение «Not Set», установите значение «None», чтобы изменение размера не возвращалось. Назад - проверено для C #, .net2.0
bh_earth0

Ответы:

132

У меня работает этот трюк:

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

Здесь происходит то, что вы устанавливаете автоматическое изменение размера в любой режим, который вам нужен, а затем столбец за столбцом вы сохраняете ширину, полученную при вычислении автоматического размера, удаляете автоматическое изменение размера и устанавливаете ширину на значение, которое вы сохранили ранее.

Мирослав Задравец
источник
1
Я поместил аналогичный код в процедуру с именем AutoResizeColumnWidthsYetAllowUserResizing. Он вызывается после первоначального заполнения сетки, а также после редактирования данных пользователем (то есть из события CellEndEdit сетки).
DeveloperDan
5
Это отличный код. Необходимо поместить в событие DataGridView1_DataSourceChanged.
user890332
1
Мне кажется, что делать grd.Columns(i).Width = grd.Columns(i).Widthуже свое дело. Смотрите здесь .
Антонио
2
для C # аналогично, но с квадратными скобками dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
barlop
Это могло произойти очень поздно, но есть ли шанс или способ изменить размер в зависимости от содержимого конкретной строки? Допустим, на основе содержимого ячеек в первой строке, независимо от ширины ячеек в других строках?
Муртуза Хусейн,
45

Может ты мог бы позвонить

dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.Fill);

После установки datasource. Он установит ширину и позволит изменять размер.

Подробнее о методе MSDN DataGridView.AutoResizeColumns (DataGridViewAutoSizeColumnsMode) .

Umair
источник
2
Я не уверен, почему этому ответу не уделяется больше внимания. Намного чище. Хотя, если вы хотите соответствовать ширине содержимого ячейки, DataGridViewAutoSizeColumnsMode.AllCells работает немного лучше.
iwalkbarefoot
31
используя это решение, я получаю следующую ошибку: «Параметр autoSizeColumnMode недействителен для этой операции. Он не может быть NotSet, None или Fill, но должен указывать критерии выбора размера». . В итоге я использовал этот dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
itsho
6
Использование DataGridViewAutoSizeColumnMode.Fill не работает, поскольку игнорирует содержимое ячейки при изменении размера столбцов.
Стюарт Хельвиг
Я использовал этот метод с DataGridViewAutoSizeColumnsMode.DisplayedCells. Кроме того, в конструкторе форм для AutoSizeColumnsMode установлено значение None. Мне нужно было выполнить этот вызов метода в обработчике событий DataBindingComplete DataGridView, чтобы убедиться, что он всегда (повторно) правильно определяет размер.
Даан
7
Я не понимаю всех голосов за ... Это вообще не работает, документация MSDN ясна, это приводит к исключению ArgumentException, если autoSizeColumnsMode имеет значение None или Fill.
Ларри
31

AC # версия кода Мирослава Задравца

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

Размещено как вики сообщества, чтобы не злиться на чужую репутацию

Том Кидд
источник
15

В моем приложении я установил

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

Кроме того, я установил

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

Теперь ширину столбцов можно изменить, и пользователь может изменить порядок столбцов. Для меня это работает очень хорошо.

Может быть, это сработает для вас.

Jehof
источник
Установка AutoSizeColumnsMode сетки на «Fill», кажется, устанавливает для всех столбцов одинаковую ширину. Да, размер столбцов можно изменить, но исходная ширина неверна. Мне может потребоваться установить ширину столбцов в коде «вручную».
Стюарт Хельвиг,
DV-сетка.AutoSizeColumnsMode = DataGridViewAutoSizeColumn-> s <- Mode.Fill; (вы пропустили s, это ColumsMode слева и справа, поэтому ваша строка не компилируется) Код для автоматического изменения размера datagridview сам по себе очень раздражает, поэтому сначала проверьте свой ответ . Это самая первая строка, которую вы написали, и она неверна.
barlop 02
@barlop благодарит за ответ. У вас есть право редактировать вопросы и ответы. Если вы заметили ошибку в моем коде, не стесняйтесь редактировать.
Jehof 02
12

После добавления данных в сетку добавьте следующий код, который настроит столбец в соответствии с длиной данных в каждой ячейке.

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

Вот результат

введите описание изображения здесь

Сарат Аванаву
источник
9

Ну я сделал вот так:

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

именно в этом порядке. Размер столбцов изменяется (расширяется), и пользователь может впоследствии изменить размер столбцов.

MPSS
источник
6

Если я правильно понял вопрос, должен быть более простой способ выполнить то, что вам нужно. Вызов dgvSomeDataGrid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);

Это должно делать свое дело. Однако есть одна ловушка, поскольку вы не можете просто вызвать этот метод сразу после заполнения элемента управления DataGridView. Вместо этого вам нужно будет добавить EventHandler для события VisibleChanged и вызвать там метод.

Горгсенеггер
источник
1
Это изменит размер столбцов в соответствии с содержимым, но не обеспечит использование всего доступного пространства сетки. Т.е. не «заполняет» оставшееся пространство, если оно есть.
Стюарт Хельвиг
5

У меня работают простые две строчки кода.

dataGridView.DataSource = dataTable;
dataGridView.AutoResizeColumns();
Рашмин Джавия
источник
4

Резюме вопроса:
адаптировать ширину столбца к содержимому (с помощью другого метода для столбца),
но затем разрешите пользователю устанавливать ширину столбца ...

Разработка от ответа Мирослава Zadravec в , для меня то , что работало сразу же с помощью автоматического вычисленного column.Widthдля набора ... 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

Это проверено на работу , когда DataGridViewуже создана, используя трюк , как это .

Антонио
источник
Я предпочитаю использовать foreach, как и ваш код. Это делает его более читаемым, когда у вас нет математики в верхней части цикла. Я так и сделал, и "column.Width = column.Width;" интересно.
Грег Барт
4

Это сделало для меня чудеса:

dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
Вайшали
источник
1
Простое решение!
Марк Крам
1
Работал для меня, только если впоследствии установить значение None, то естьdataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
Do-do-new
3

Это автоматически заполняет все столбцы в соответствии с их содержимым, заполняет оставшееся пустое пространство, растягивая указанный столбец, и предотвращает поведение «прыжков», задавая последний столбец для заполнения для любого будущего изменения размера.

// 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
источник
Я знаю, что это старый ответ, но я работаю хорошо, даже когда количество столбцов не известно заранее.
Нило Пайм
2

Немного более аккуратный код C # из кода Мирослава Задравца, предполагающий, что все столбцы должны быть автоматически изменены

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

Еще одна версия кода Мирослава Задравца, но чуть более автоматизированная и универсальная:

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

Я помещаю вторую часть в отдельное событие, потому что я заполняю datagridvewинициализацию формы, и если обе части присутствуют, ничего не меняется, потому что, вероятно, автоматическое изменение размера вычисляет ширину после datagridviewотображения, поэтому ширина по-прежнему остается в Form1()методе по умолчанию . После завершения этого метода autosize делает свое дело, и сразу после этого (когда форма отображается) мы можем установить ширину второй частью кода (здесь, в Form1Shownслучае). Это работает для меня как шарм.

LQd
источник
2

Вот упрощенный код для ответа Мирослава Задравца на С #:

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

Вы пытались настроить FillWeightсвойство вашегоDataGridViewColumns объекта?

Например:

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

Думаю, в вашем случае это должно сработать.

Алексей Рубановский
источник
1

Небольшое улучшение по сравнению с версией 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
источник
1

dataGridView1.AutoResizeColumns ();

Ник Андриопулос
источник
1

Ширина столбца настроена так, чтобы соответствовать его содержимому. Я использовал приведенное ниже утверждение. Это решило мою проблему.

Первый шаг :

RadGridViewName.AutoSize = true;

Второй шаг :

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

Третий шаг:

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

Это должно работать независимо от того dataGridView, был ли он отображен (т.е. даже если он был вызван из конструктора класса).

Тот же метод, но с DataGridViewAutoSizeColumnMode.DisplayedCells, в приведенном выше случае не работает по очевидной причине - ячейка еще не отображалась! По какой-то неочевидной причине AutoResizeColumnsв этом случае тоже не работает.

Вечная ночь
источник
0

Например, если вы привязываете свой источник данных к таблице данных, вам необходимо установить свойства после того, как привязка будет выполнена:

        private void dgv_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
            dgv.AutoResizeColumns();
            dgv.AllowUserToResizeColumns = true;
        }
эхх
источник
0
  • Спасибо за решение выше (чтобы выполнить итерацию DataGridView.Columns, измените AutoSizeModeзначение на действительное, соберите значение ширины и верните его после изменения AutoSizeModeнаDataGridViewAutoSizeColumnMode.None ).
  • Я боролся с этим и заметил, что он не будет работать всякий раз, когда он вызывается из конструктора класса или любой строки до Form.Show()или Form.ShowDialog(). Поэтому я поместил этот фрагмент кода в Form.Shownсобытие, и у меня это сработало.
  • Мой преобразованный код, независимо от того, что было DataGridView.AutoSizeColumnsModeустановлено ранее, я использую DataGridViewColumn.GetPreferredWidth()вместо того, чтобы сразу менять DataGridViewColumn.AutoSizeModeи устанавливать значение ширины, а затем изменить DataGridView.AutoSizeColumnsModeодин раз:

    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;
    }
  • Обязательно установите

            dataGridView.AllowUserToResizeColumns = true;
  • Я не знаю, почему это работает только после отображения формы.

user1779049
источник
0

Мне пришлось сделать это в VB, и я предпочитаю разделить это на метод, который я поместил в модуль. При желании вы можете добавить столбец «Заливка» в качестве еще одного параметра 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
Грег Барт
источник
0

Вы можете сделать что-то вроде этого:

   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;

Все столбцы адаптируются к содержимому, за исключением последнего, заполняющего сетку.

usr4217
источник
0

Если $ array является содержимым PSCustomObject, это работает:

$dataGridView1.DataSource=[collections.arraylist]($array)
$dataGridView1.Columns | Foreach-Object{$_.AutoSizeMode = [System.Windows.Forms.DataGridViewAutoSizeColumnMode]::AllCells}
Wtcunningham
источник