InvalidOperationException: this operation cannot be performed while resizing an autocomplete column

I have a form with a DataGridView and I want to set AutoSizeMode columns to Fill and ColumnHeadersHeightSizeMode grids to AutoSize . My problem is that if the mouse accidentally hovers over the top left cell of the grid when the form loads, the application throws an InvalidOperationException .

This is what I should see when the form loads: enter image description here (Notice how the cursor hovers over the top left cell).

This code will throw an exception:

 static class Program { [STAThread] static void Main() { // Make sure the mouse will hover upper left cell when the form loads: var form = new MyForm { StartPosition = FormStartPosition.Manual }; form.SetDesktopLocation(Cursor.Position.X - 30, Cursor.Position.Y - 40); Application.Run(form); } class MyForm : Form { public MyForm() { var grid = new DataGridView { Dock = DockStyle.Fill }; grid.Columns.Add("ColumnName", "HeaderText"); // The form will load if I remove one of the two next lines: grid.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; grid.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; Controls.Add(grid); } } } 

In my configuration, Visual Studio swallows an exception, so I have to start the application from Windows Explorer or the command line to see the error.

This is stacktrace:

 System.InvalidOperationException: This operation cannot be performed while an auto-filled column is being resized. at System.Windows.Forms.DataGridView.PerformLayoutPrivate(Boolean useRowShortcut, Boolean computeVisibleRows, Boolean invalidInAdjustFillingColumns, Boolean repositionEditingControl) at System.Windows.Forms.DataGridView.SetColumnHeadersHeightInternal(Int32 columnHeadersHeight, Boolean invalidInAdjustFillingColumns) at System.Windows.Forms.DataGridView.AutoResizeColumnHeadersHeight(Boolean fixedRowHeadersWidth, Boolean fixedColumnsWidth) at System.Windows.Forms.DataGridView.OnColumnHeadersGlobalAutoSize() at System.Windows.Forms.DataGridView.set_TopLeftHeaderCell(DataGridViewHeaderCell value) at System.Windows.Forms.DataGridView.get_TopLeftHeaderCell() at System.Windows.Forms.DataGridView.GetCellInternal(Int32 columnIndex, Int32 rowIndex) at System.Windows.Forms.DataGridView.OnCellMouseEnter(DataGridViewCellEventArgs e) at System.Windows.Forms.DataGridView.UpdateMouseEnteredCell(HitTestInfo hti, MouseEventArgs e) at System.Windows.Forms.DataGridView.OnColumnWidthChanged(DataGridViewColumnEventArgs e) at System.Windows.Forms.DataGridView.OnBandThicknessChanged(DataGridViewBand dataGridViewBand) at System.Windows.Forms.DataGridViewBand.set_ThicknessInternal(Int32 value) at System.Windows.Forms.DataGridView.AdjustFillingColumns() at System.Windows.Forms.DataGridView.ComputeLayout() at System.Windows.Forms.DataGridView.PerformLayoutPrivate(Boolean useRowShortcut, Boolean computeVisibleRows, Boolean invalidInAdjustFillingColumns, Boolean repositionEditingControl) at System.Windows.Forms.DataGridView.OnHandleCreated(EventArgs e) at System.Windows.Forms.Control.WmCreate(Message& m) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.DataGridView.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 

Two questions relate to the same problem: here and here , but the application still crashes when I apply the suggested answers.

Am I violating some good practices in the above example? Has anyone come across this behavior and knew a workaround?

+3
source share
3 answers

This seems to be a mistake - the code is trying to access dataGridView.TopLeftHeaderCell , which, when it happens for the first time, actually creates this cell and starts some layout actions that are not expected at this moment.

Given all this, the fix is ​​simple. We need to make sure that TopLeftHeaderCell created before the DataGridView descriptor by adding the following line (for example, before adding a grid to Controls )

 var topLeftHeaderCell = grid.TopLeftHeaderCell; // Make sure TopLeftHeaderCell is created 
+5
source

Thank you, Ulf, for a great sample showing how to reproduce this. One of my clients reported this to me, and your sample was invaluable.

Taking Ivan's excellent answer one step further, creating your own grid inheriting from the DataGridView should constantly prevent this ridiculous error. Just remember to always use custom grids throughout the application.

 public class Grid : DataGridView { protected override void OnHandleCreated(EventArgs e) { // Touching the TopLeftHeaderCell here prevents // System.InvalidOperationException: // This operation cannot be performed while // an auto-filled column is being resized. var topLeftHeaderCell = TopLeftHeaderCell; base.OnHandleCreated(e); } } 
+2
source

You report that the main stream drawing interface.

In fact, you process the drawing (initial position) before starting the application and before the layout operation (controls) are fully initialized inside the layout pause block.

Changing your approach allows you to solve the problem (no need to change the code, add only some fragments).

 static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MyForm()); } public class MyForm : Form { public MyForm() { this.InitializeComponents(); } private void MyForm_Shown(object sender, EventArgs e) { this.SetDesktopLocation(Cursor.Position.X - 30, Cursor.Position.Y - 40); } private void InitializeComponents() { this.SuspendLayout(); this.StartPosition = FormStartPosition.Manual ; var grid = new DataGridView { Dock = DockStyle.Fill }; grid.Columns.Add("ColumnName", "HeaderText"); // The form will load if I remove one of the two next lines: grid.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; grid.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; Controls.Add(grid); this.Shown += new System.EventHandler(this.MyForm_Shown); this.ResumeLayout(false); } } } 
0
source

All Articles