Bug 9653 - DataGridView after one cell is edited crashes when selecting a second cell
Summary: DataGridView after one cell is edited crashes when selecting a second cell
Status: RESOLVED FIXED
Alias: None
Product: Class Libraries
Classification: Mono
Component: Windows.Forms (show other bugs)
Version: unspecified
Hardware: PC Linux
: Lowest normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
: 22297 26070 (view as bug list)
Depends on:
Blocks:
 
Reported: 2013-01-17 12:30 UTC by djdjaa89
Modified: 2016-08-05 16:29 UTC (History)
9 users (show)

See Also:
Tags: mono-community
Is this bug a regression?: ---
Last known good build:


Attachments
A program that invokes this bug (586 bytes, text/plain)
2013-03-20 15:05 UTC, djdjaa89
Details
A collection of errors/whatever in Winform's DataGridView (86.04 KB, application/pdf)
2015-01-03 12:04 UTC, Baltasar
Details

Description djdjaa89 2013-01-17 12:30:45 UTC
To reproduce this crash:

- run SimpleDataGridView.cs
- edit a cell
- click on other cells
- will crash in a reproducible manner with this stack trace on my computer, using multiple mono runtimes, and different window managers in linux:

System.ObjectDisposedException: The object was used after being disposed.
  at System.Windows.Forms.Control.CreateHandle () [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.TextBoxBase.CreateHandle () [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.CreateControl () [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.SetVisibleCore (Boolean value) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.set_Visible (Boolean value) [0x00000] in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) System.Windows.Forms.Control:set_Visible (bool)
  at System.Windows.Forms.DataGridView.BeginEdit (Boolean selectAll) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.DataGridView.SetCurrentCellAddressCore (Int32 columnIndex, Int32 rowIndex, Boolean setAnchorCellAddress, Boolean validateCurrentCell, Boolean throughMouseClick) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.DataGridView.OnMouseDown (System.Windows.Forms.MouseEventArgs e) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.WmLButtonDblClick (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.WndProc (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.DataGridView.WndProc (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control+ControlWindowTarget.OnMessage (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control+ControlNativeWindow.WndProc (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.NativeWindow.WndProc (IntPtr hWnd, Msg msg, IntPtr wParam, IntPtr lParam) [0x00000] in <filename unknown>:0 
System.ArgumentOutOfRangeException: Index is less than 0 or more than or equal to the list count.
Parameter name: index
0
  at System.Collections.ArrayList.ThrowNewArgumentOutOfRangeException (System.String name, System.Object actual, System.String message) [0x00000] in <filename unknown>:0 
  at System.Collections.ArrayList.get_Item (Int32 index) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.DataGridViewRowCollection.SharedRow (Int32 rowIndex) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.DataGridView.GetRowInternal (Int32 rowIndex) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.DataGridView.GetCellInternal (Int32 colIndex, Int32 rowIndex) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.DataGridView.OnCellLeave (System.Windows.Forms.DataGridViewCellEventArgs e) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.DataGridView.SetCurrentCellAddressCore (Int32 columnIndex, Int32 rowIndex, Boolean setAnchorCellAddress, Boolean validateCurrentCell, Boolean throughMouseClick) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.DataGridView.MoveCurrentCell (Int32 x, Int32 y, Boolean select, Boolean isControl, Boolean isShift, Boolean scroll) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.DataGridView.OnColumnCollectionChanged (System.Object sender, System.ComponentModel.CollectionChangeEventArgs e) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.DataGridViewColumnCollection.OnCollectionChanged (System.ComponentModel.CollectionChangeEventArgs e) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.DataGridViewColumnCollection.Clear () [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.DataGridView.Dispose (Boolean disposing) [0x00000] in <filename unknown>:0 
  at System.ComponentModel.Component.Dispose () [0x00000] in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) System.ComponentModel.Component:Dispose ()
  at System.Windows.Forms.Control.Dispose (Boolean disposing) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.ContainerControl.Dispose (Boolean disposing) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Form.Dispose (Boolean disposing) [0x00000] in <filename unknown>:0 
  at System.ComponentModel.Component.Dispose () [0x00000] in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) System.ComponentModel.Component:Dispose ()
  at System.Windows.Forms.Form.WmClose (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Form.WndProc (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control+ControlWindowTarget.OnMessage (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control+ControlNativeWindow.WndProc (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.NativeWindow.WndProc (IntPtr hWnd, Msg msg, IntPtr wParam, IntPtr lParam) [0x00000] in <filename unknown>:0 


SimpleDataGridView.cs:

using System;
using System.Drawing;
using System.Windows.Forms;

class MyClass : Form
{
    [STAThread]
    public static void Main()
    {
        Application.Run(new MyClass());
    }
    public MyClass()
    {
        Text = "Simple DataGridView";

        DataGridView grid = new DataGridView();
        grid.Parent = this;
        grid.AutoSize = true;
        grid.Dock = DockStyle.Fill;
        grid.ColumnCount = 3;
        grid.Columns[0].HeaderText = "First Name";
        grid.Columns[1].HeaderText = "Last Name";
        grid.Columns[2].HeaderText = "Email Address";
    }
}


information about my software:

Linux sean-dell 3.7-1.slh.1-aptosid-amd64 #1 SMP PREEMPT Tue Dec 18 15:16:57 UTC 2012 x86_64 GNU/Linux

Package: x11-common
Status: install ok installed
Priority: optional
Section: x11
Installed-Size: 466
Maintainer: Debian X Strike Force <debian-x@lists.debian.org>
Architecture: all
Multi-Arch: foreign
Source: xorg
Version: 1:7.7+1
Comment 1 djdjaa89 2013-03-20 13:13:54 UTC
Is there any other information I need to provide to have this looked at?
Comment 2 djdjaa89 2013-03-20 15:05:55 UTC
Created attachment 3666 [details]
A program that invokes this bug

This is a test case, it works with wine:

wine SimpleDataGridView.exe

after it is compiled
Comment 3 Baltasar 2014-04-29 04:47:38 UTC
Same here. 

I'm using Mono 3.2.8 in Lubuntu 14.04, and I'm observing an odd behaviour which renders a WinForms app unusable. This application works perfectly in Windows, I mean, with the .NET stack, and worked perfectly in the previous version of Lubuntu (with an older version of Mono).

	The app has a DataGridView. The problem is that, the second time you try to write something in a cell, WinForms launches the following exception (below). After this exception, the second time you write in the datagridview cell, the exception is raised continuously, so you actually cannot use the app.

==
$ mono ../pgcal/pgcal/bin/Release/pgcal.exe 
System.ObjectDisposedException: The object was used after being disposed.
  at System.Windows.Forms.Control.CreateHandle () [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.TextBoxBase.CreateHandle () [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.CreateControl () [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.SetVisibleCore (Boolean value) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.set_Visible (Boolean value) [0x00000] in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) System.Windows.Forms.Control:set_Visible (bool)
  at System.Windows.Forms.DataGridView.BeginEdit (Boolean selectAll) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.DataGridView.ProcessKeyEventArgs (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.ProcessKeyMessage (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.WmKeys (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.WndProc (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.DataGridView.WndProc (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control+ControlWindowTarget.OnMessage (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control+ControlNativeWindow.WndProc (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.NativeWindow.WndProc (IntPtr hWnd, Msg msg, IntPtr wParam, IntPtr lParam) [0x00000] in <filename unknown>:0 
System.ObjectDisposedException: The object was used after being disposed.
  at System.Windows.Forms.Control.CreateHandle () [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.TextBoxBase.CreateHandle () [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.get_Handle () [0x00000] in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) System.Windows.Forms.Control:get_Handle ()
  at System.Windows.Forms.DataGridView.ProcessKeyEventArgs (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.ProcessKeyMessage (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.WmKeys (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control.WndProc (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.DataGridView.WndProc (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control+ControlWindowTarget.OnMessage (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.Control+ControlNativeWindow.WndProc (System.Windows.Forms.Message& m) [0x00000] in <filename unknown>:0 
  at System.Windows.Forms.NativeWindow.WndProc (IntPtr hWnd, Msg msg, IntPtr wParam, IntPtr lParam) [0x00000] in <filename unknown>:0
==
Comment 4 Baltasar 2014-04-29 04:49:17 UTC
This bug should be marked as IMPORTANT, since renders any app making use of the datagridview component unusable.
Comment 5 soujisetap4p 2014-12-31 02:28:19 UTC
This issued looks to be caused by a combination of the DataGridViewTextBoxCell::editingControl static member and the DataGridView::EditingControlInternal setter.

The DataGridViewTextBoxCell::editingControl object is declared as a
private static DataGridViewTextBoxEditingControl editingControl near the top of the DataGridViewTextBoxCell.cs file.

When EditingControlInternal sets a new control it calls dispose on the previous editingControl if one exist. Here is the snippet below

if (editingControl != null) {
   // Can't use Controls.Remove (editingControls), because that method
   // is overriden to not remove the editing control.
   DataGridView.DataGridViewControlCollection ctrls = Controls as 
      DataGridView.DataGridViewControlCollection;
   if (ctrls != null) {
       ctrls.RemoveInternal (editingControl);
    } else {
       Controls.Remove (editingControl);
    }
    editingControl.Dispose();
}

When a text cell is edited the DataGridViewTextBoxCell::InitializeEditingControl  method is invoked with this line
DataGridView.EditingControlInternal = editingControl;

This sets the DataGridView::editingControl to point to the static DataGridViewTextBoxCell::editingControl. When another cell in the DataGridView is edited, the static DataGridViewTextBoxCell::editingControl member gets the dispose method called on it.

A potential solution to this problem is to not call dispose on the editingControl if it is a static field.
Comment 6 Baltasar 2014-12-31 06:49:33 UTC
Yes, soujisetap4p@gmail.com, I had arrived to the same conclusion. My plan was to do a quick fix, build WinForms and submit a patch. Unfortunately, I was unable to build WinForms, and apparently nobody was able to help me (it seems nobody builds WinForms anymore).
Comment 7 soujisetap4p 2014-12-31 14:14:58 UTC
Well I was able to build the mono project from the github source by pulling the repo and performing the commands

./autogen.sh
make update_submodules 
make
make install

I had issues building the project until I found out that I needed to "update_submodules" target of the Makefile for pulling in the external dependencies.

Furthermore I removed the Dispose() call in the EditingControlInternal setter and that fixes the issue. I am guessing the explicit Dispose() call is for cleaning up the managed resources immediately, but is probably not needed as the control will be picked up by GC later.
Comment 8 Baltasar 2015-01-01 05:11:40 UTC
My issue had to do with keyboard layouts. Anyway, I do agree that the problem is solved by removing that call to Dispose(), so... let's hope that the Xamarin guys do the fix quickly.
Comment 9 soujisetap4p 2015-01-01 13:35:54 UTC
I created a pull request for the fix to issue here https://github.com/mono/mono/pull/1486
Comment 10 Miguel de Icaza [MSFT] 2015-01-03 09:43:20 UTC
Thanks for the investigation into this issue and submitting the pull request, that was the key.

That said, the current proposal is a band-aid.

While the analysis for the static issue is correct, I doubt very much that the correct approach is to remove the Dispose() from the code.

The major issue is that we have a static editingControl in the first place, and that this instance gets reused.   For one, this would break if you have more than one DataGridView on the screen.

I have tried a different patch, can you please try it.   It is now on git.
Comment 11 Miguel de Icaza [MSFT] 2015-01-03 09:44:01 UTC
*** Bug 22297 has been marked as a duplicate of this bug. ***
Comment 12 Baltasar 2015-01-03 12:03:37 UTC
I cannot test it because, as I said, I'm unable to build WinForms by myself. I won't insist in the same point.

Maybe the action of removing Dispose() from the code is not the most correct solution, but given the attention that WinForms receives (this bug has been open sice Jan 2013, two years ago), it is better to have that implemented than anything.

While diving into the WinForms code, I found some interesting implementation details that I began to collect in a document. I'm attaching it to this bug since the errors I collected are related to GridView. Feel free to use this info as you like.
Comment 13 Baltasar 2015-01-03 12:04:41 UTC
Created attachment 9235 [details]
A collection of errors/whatever in Winform's DataGridView
Comment 14 Miguel de Icaza [MSFT] 2015-01-03 13:05:19 UTC
Here you can find a binary of the library, that you can install with:

gacutil /i System.Windows.Forms.dll

http://tirania.org/tmp/System.Windows.Forms.dll
Comment 15 soujisetap4p 2015-01-03 14:34:04 UTC
I will pull the latest changes and test if the issue is fixed.
Comment 16 soujisetap4p 2015-01-03 16:21:01 UTC
I have tested the latest changes and verified that the issue is fixed.
Comment 17 Stephen McConnel 2015-01-15 12:04:51 UTC
*** Bug 26070 has been marked as a duplicate of this bug. ***
Comment 18 Aris 2015-11-02 00:46:15 UTC
I was looking for a fix regarding this datagridview issue and found this bug 9653.

It mentioned that the issue was fixed.  I'm using Mono 4.0.3 for windows and 4.0.4 for Fedora 19,  but found that this issue still exists. The winform application crashes when editing another cell in a datagridview.
Comment 19 Daniel.LOCHE 2016-08-05 16:29:22 UTC
The bug is still there !! :/
A way to solve it ?

Note You need to log in before you can comment on or make changes to this bug.