如何在 DataGridView 上获得自动调整的列宽以减少填充?

How can I get autosized column widths on a DataGridView to be less generous with padding?

我将 AutoSizeColumnMode 和 AutoSizeRowsMo​​de 设置为 AllCells。这解决了所有列宽度相同的问题,使其中一些列太窄,但现在有些列太宽了,浪费了所需的空间(我想去掉的区域用红色矩形表示):

我发现 this answer 类似的问题:

dataGridView1.Columns[1].Width = 40;

...十年前被作者删掉了,但感觉还是有道理的,于是试了一下:

dataGridView1.Columns[1].Width = 40;
dataGridView1.Columns[2].Width = 40;
dataGridView1.Columns[3].Width = 40;
dataGridView1.Columns[4].Width = 40;

...但这没有任何区别。我什至将“40”更改为“4”只是为了确定,但仍然没有变化。所以我不知道文本值是否有边距或填充,或者发生了什么,但我想“收紧”列的宽度,使其仅显示内容所需的宽度(以及 header 文本)仅此而已。我怎样才能做到这一点?

不幸的是,开箱即用 DataGridView 在对列使用“自动调整大小”选项时并不过分复杂。例如,如果您将“网格”AutoSizeColumnsMode 设置为 Fill,它会自动将 100 列填充到一个非常小的 space.

此外,当存在两 (2) 个不同的 AutoSizeColumn 属性时,事情会变得更加复杂。可以在“GRID”上使用的DataGridViewAutoSizeColumnsMode。除了可以在单个“COLUMNS”上使用的 DataGridViewAutoSizeColumnMode。注意:与后者缺少“s”(列)的区别。

这可能会引起一些混乱。在您上面描述的情况下的示例,如果您将“网格”DataGridViewAutoSizeColumnsMode 设置为 .AllCells... 那么网格将根据单元格中显示的内容将每一列设置为特定宽度。如果可能,网格将根据该列中最长的文本行确定列宽,包括 header。这将覆盖任何单独的列宽设置。这就是为什么当“网格”自动列大小模式设置为 AllCells.

时,更改“个人”列宽度没有效果的原因

我的理解是,如果存在冲突,每列的“单独”设置将“覆盖”网格设置。如果未设置列 AutoSizeMode,则将应用网格设置。这来自文档,但是从您的问题可以看出,情况并非总是如此。这通常取决于“GRIDS”自动列大小设置是什么。

我发现删除“GRIDS”自动列功能并将“每个”单独的列设置为特定的自动大小模式似乎以更直观的方式工作。当然,它需要更多工作,但是,它可以让您更好地控制列的宽度。

因此,我过去使用的方法……假设列“将”适合网格的宽度,是将我想要的列的列宽“固定”为特定宽度。然后为了填充网格,我会将一两列设置为“填充”。这几乎可以保证固定宽度的列不会改变,您可以将宽度设置为任何有效值。但是,其他 non-fixed 列的宽度可能会改变。

下面是上述内容的完整示例。有五 (5) 列。内部三 (3) 列为固定宽度,外部列设置为“填充”。显然,如果您将所有列都设置为固定宽度,那么末尾可能会出现间隙并且无法填充网格宽度。要填充网格,必须至少将一 (1) 列设置为“填充”。

考虑到,您的最后一个问题涉及获取列以设置 DataPropertyName,将这些附加属性添加到该方法似乎是合适的。我可能看起来像下面...

private DataGridViewTextBoxColumn GetColumnForGrid2(string colName, string colHeader, string dataPropertyName, int width, DataGridViewAutoSizeColumnMode mode) {
  DataGridViewTextBoxColumn dgvc = new DataGridViewTextBoxColumn();
  dgvc.Name = colName;
  dgvc.HeaderText = colHeader;
  dgvc.DataPropertyName = dataPropertyName;
  dgvc.AutoSizeMode = mode;
  dgvc.Width = width;
  return dgvc;
}

然后完成上图中的例子

BindingList<MoviesSingleTable> MovieList;

private void Form1_Load(object sender, EventArgs e) {
  MovieList = GetData();
  DataGridViewColumn col = GetColumnForGrid2("MovieTitle", "Title", "MovieTitle", 40, DataGridViewAutoSizeColumnMode.Fill);
  dataGridView1.Columns.Add(col);
  col = GetColumnForGrid2("IMDBRating", "IMDB", "IMDBRating", 40, DataGridViewAutoSizeColumnMode.None);
  dataGridView1.Columns.Add(col);
  col = GetColumnForGrid2("MPAARating", "MPAA", "MPAARating", 40, DataGridViewAutoSizeColumnMode.None);
  dataGridView1.Columns.Add(col);
  col = GetColumnForGrid2("Duration", "Duration", "durationInMinutes", 40, DataGridViewAutoSizeColumnMode.None);
  dataGridView1.Columns.Add(col);
  col = GetColumnForGrid2("Year", "Year", "YearReleased", 35, DataGridViewAutoSizeColumnMode.Fill);
  dataGridView1.Columns.Add(col);
  dataGridView1.AutoGenerateColumns = false;
  dataGridView1.DataSource = MovieList;
}

示例数据...

private BindingList<MoviesSingleTable> GetData() {
  BindingList<MoviesSingleTable> bl = new BindingList<MoviesSingleTable>();
  MoviesSingleTable mgdc = new MoviesSingleTable {
    MovieTitle = "The Princess Bride",
    IMDBRating = 8.1,
    MPAARating = "PG",
    durationInMinutes = 98,
    YearReleased = "1987",
    genres = "g",
    actors = "a",
    directors = "d",
    screenwriters = "s"
  };
  bl.Add(mgdc);

  mgdc = new MoviesSingleTable() {
    MovieTitle = "Will Penny",
    IMDBRating = 7.1,
    MPAARating = "PG-13",
    durationInMinutes = 108,
    YearReleased = "1967",
    genres = "",
    actors = "",
    directors = "",
    screenwriters = ""
  };
  bl.Add(mgdc);

  mgdc = new MoviesSingleTable() {
    MovieTitle = "2001 A Space Odysee",
    IMDBRating = 7.1,
    MPAARating = "NR",
    durationInMinutes = 108,
    YearReleased = "1967",
    genres = "",
    actors = "",
    directors = "",
    screenwriters = ""
  };
  bl.Add(mgdc);

  mgdc = new MoviesSingleTable() {
    MovieTitle = "The Gods Must Be Crazy",
    IMDBRating = 7.1,
    MPAARating = "PG",
    durationInMinutes = 108,
    YearReleased = "1967",
    genres = "",
    actors = "",
    directors = "",
    screenwriters = ""
  };
  bl.Add(mgdc);
  return bl;
}