InvalidOperationException: This operation cannot be performed while an auto-filled column is being resized

后端 未结 4 942
暖寄归人
暖寄归人 2021-02-15 00:30

I have a form with a DataGridView and I want to set the columns AutoSizeMode to Fill and the grids ColumnHeadersHeightSizeMode

相关标签:
4条回答
  • 2021-02-15 01:00

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

    With all that in mind, the fix is simple. We need to make sure that the TopLeftHeaderCell is created before DataGridView handle, by adding the following line (before affffding the grid to Controls for instance)

    var topLeftHeaderCell = grid.TopLeftHeaderCell; // Make sure TopLeftHeaderCell is created
    
    0 讨论(0)
  • 2021-02-15 01:02

    In .net core (3.1.9) and .net5.0 this is not reproducible. There was no directly fix, but somehow there are no exception any more. See (and post if you still have this issue): https://github.com/dotnet/winforms/issues/1830.

    0 讨论(0)
  • 2021-02-15 01:04

    Thank you, Ulf, for the excellent sample showing how to reproduce this. One of my clients reported this bug to me and your sample has been invaluable.

    Taking Ivan's excellent answer one step further, creating your own grid inheriting from the DataGridView should prevent this ridiculous bug permanently. Just be sure to always use the custom grid throughout your 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);
        }
    }
    
    0 讨论(0)
  • 2021-02-15 01:12

    You issue is related with the fact that main thread draw interface.

    Actually you handle drawing (starting position) before application run is launched and before layout operation (controls) are all completly initialize inside suspend layout block.

    Changing your approach solve the issue (no need to change your code, only add some pieces).

    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 讨论(0)
提交回复
热议问题