The problem is old, but still present, so even after all this time another workaround could prove to be useful.
Recently I had the same issue, and did not find a perfect solution, but in my situation, the solution I finally came up with was the least annoying compared to what I found.
Since the auto size is buggy by nature, the only way seemed to be a re-implementation using events.
The question is about C#, and I only have a PowerShell example, because that's what I used when I encountered this issue, but the root cause is in WinForms, and Powershell uses the same thing, through a slightly different API.
This means, that the example below shows the major steps for a workaround that can be done using C# as well.
# Import
Add-Type -assembly System.Windows.Forms
# Initialize main form
$window = New-Object System.Windows.Forms.Form
$window.Text ='Test App'
# This is for the window to follow the content
# Although this is technically not relevant, it can limit the options for the workaround because this auto size is not always able to follow the weirdness that's going on
$window.AutoSize = $true
# Create columns
$dataTable = New-Object System.Data.DataTable
$dataTable.Columns.Add("Col1", [System.Type]::GetType("System.Int32"))
$dataTable.Columns.Add("Col2", [System.Type]::GetType("System.Int32"))
# Initialize DataGridView
$grid = New-Object System.Windows.Forms.DataGridView
$grid.DataSource = $dataTable
# These can be anything, but will affect what the sizing needs to be exactly
$grid.ColumnHeadersVisible = $true
$grid.RowHeadersVisible = $true
$grid.BorderStyle = 0
# These are not required, the point is that it works even if the user is poking around
$grid.ReadOnly = $false
$grid.AllowUserToAddRows = $true
$grid.AllowUserToDeleteRows = $true
$grid.AllowUserToOrderColumns = $true
$grid.AllowUserToResizeColumns = $true
$grid.AllowUserToResizeRows = $true
$resizeLogic = {
# The height and width of the actual grid are available so that the host can be resized to the same size. Note, that this is affected by having the header and any borders
# See the doc for the magic zeroes: https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.datagridviewelementstates?view=windowsdesktop-8.0
$grid.Height = $grid.Rows.GetRowsHeight(0) + $grid.ColumnHeadersHeight
$grid.Width = $grid.Columns.GetColumnsWidth(0) + $grid.RowHeadersWidth
# The resize above seems to somehow dodge the main frame's auto-sizing, so this is a gentle reminder.
# Note, that this limits the Events that can be used as resizing the window triggers some rendering-related events of the grid view
$window.Height = 0
$window.Width = 0
}
# Register all events that can impact the size
$grid.Add_RowHeightChanged($resizeLogic)
$grid.Add_ColumnWidthChanged($resizeLogic)
$grid.Add_RowsAdded($resizeLogic)
$grid.Add_RowsRemoved($resizeLogic)
$grid.Add_ColumnAdded($resizeLogic)
$grid.Add_ColumnRemoved($resizeLogic)
# Just some dummy rows
$dataTable.Rows.Add(1)
$dataTable.Rows.Add(2)
# Assemble and show the window
$window.Controls.Add($grid)
$window.ShowDialog()
Note that this is a situational solution, but I liked it compared to making the grid view background "invisible", because this way there is no random dead space, even if it's less visible.
There are two downsides to this though:
- The resize looks awful (meaning that the content goes black and re-renders cell-by-cell. Deleting multiple rows could be an epilepsy danger zone to be honest)
- The last row and column cannot be increased in size, because the cursor can only move within the grid view host area (this may be a reason why the unused area is there, and could probably be worked around, but this was enough for me)