如何在 DataGridView 上获得自动调整的列宽以减少填充?
How can I get autosized column widths on a DataGridView to be less generous with padding?
我将 AutoSizeColumnMode 和 AutoSizeRowsMode 设置为 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;
}
我将 AutoSizeColumnMode 和 AutoSizeRowsMode 设置为 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;
}