I set AutoSizeColumnMode AND AutoSizeRowsMode to AllCells. This solved the problem of all columns being the same width, making some of them too narrow, but now there are columns that are too wide, wasting needed real estate (areas I want to strip out are rectangled in red):
I found this answer to a similar question:
dataGridView1.Columns[1].Width = 40;
...which was deleted by the author a decade back, but it seemed sensible, so I tried it:
dataGridView1.Columns[1].Width = 40;
dataGridView1.Columns[2].Width = 40;
dataGridView1.Columns[3].Width = 40;
dataGridView1.Columns[4].Width = 40;
...but it made no difference whatsoever. I even changed the "40" to "4" just to make sure, and still no change. So I don't know if the text values have margin, or padding, or what's going on, but I want to "tighten up" the width of the columns to be only what is needed to show the contents (and the header text) and nothing more. How can I accomplish that?
Unfortunately, the out of the box DataGridView
is not overly sophisticated when using the “auto size” option for the columns. Example, if you set the “grids” AutoSizeColumnsMode
to Fill
, it will obligingly cram 100 columns into a very small space.
In addition, things get more complicated when there are two (2) different AutoSizeColumn
properties. The DataGridViewAutoSizeColumnsMode
which can be used on the “GRID.” In addition to the DataGridViewAutoSizeColumnMode
which can be used on the individual “COLUMNS”. NOTE: the difference with the missing “s” (Column) on the latter.
This can cause some confusion. Example in the case you are describing above, if you set the “grids” DataGridViewAutoSizeColumnsMode
to .AllCells
… then the grid will set each column to a specific width depending on what is displayed in the cells. If possible, the grid will determine the columns width based on the longest line of text in that column, including the header. This will override any individual column width setting. This is why, changing the “individual” columns width has no effect when the “grids” auto column size mode is set to AllCells
.
My understanding is that the “individual” setting for each column will “override” the grids setting if there is a conflict. If the columns AutoSizeMode
is NOT set, then the grids settings will apply. This comes from the documentation, however as seen from your question, this is not necessarily always the case. This will often depend on what the “GRIDS” auto column size setting is.
I have found that dropping the “GRIDS” auto column feature and instead setting “each” individual column to a specific auto size mode appears to work in a more intuitive manner. Granted it is more work, however, it gives you more control over the widths of the columns.
Therefore, the approach I have used in the past… assuming the columns “will” fit in the grid’s width, is to “fix” the column widths of the columns I want to be a particular width. Then to fill the grid, I will set one or two columns to “Fill.” This will pretty much guarantee the fixed width columns will NOT change and you can set the width to any valid value. However, the other non-fixed column widths may change.
Below is a full example of what is described above. There are five (5) columns. The inner three (3) columns are fixed widths and the outer columns are set to “fill.” Obviously, if you make all columns with a fixed width, then there may be a gap at the end and not fill the grids width. To fill the grid, at least one (1) column must be set to “Fill.”
Considering, your last question involved getting the columns to set the DataPropertyName
, it seems appropriate to add these additional properties to that method. I may look like below…
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;
}
Then to complete the example from the picture above.
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;
}
Sample Data...
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;
}