DataGridView bound to dataset's related grandchild with no records raises System.InvalidOperationException
See original GitHub issue-
.NET Core Version: 5
-
Have you experienced this same bug with .NET Framework?: Yes
Problem description:
Dataset with 3 tables: Parent, Child, Grandchild, and 2 DataRelations: Child->Parent, Grandchild->Child. DataGridView added to form. Setting the DataGridView’s DataSource to the Parent and DataMember to Grandchild results in: System.InvalidOperationException: ‘Item cannot be added to a read-only or fixed-size list.’
System.InvalidOperationException
HResult=0x80131509
Message=Item cannot be added to a read-only or fixed-size list.
Source=System.Windows.Forms
StackTrace:
at System.Windows.Forms.BindingSource.AddNew()
at System.Windows.Forms.CurrencyManager.AddNew()
at System.Windows.Forms.RelatedCurrencyManager.ParentManager_CurrentItemChanged(Object sender, EventArgs e)
at System.Windows.Forms.RelatedCurrencyManager.Bind(BindingManagerBase parentManager, String dataField)
at System.Windows.Forms.BindingContext.EnsureListManager(Object dataSource, String dataMember)
at System.Windows.Forms.DataGridView.DataGridViewDataConnection.SetDataConnection(Object dataSource, String dataMember)
at System.Windows.Forms.DataGridView.set_DataMember(String value)
at Deleteme.Form1.Form1_Load(Object sender, EventArgs e) in C:\...\Form1.vb:line 26
at System.Windows.Forms.Form.OnLoad(EventArgs e)
at System.Windows.Forms.Form.OnCreateControl()
at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
at System.Windows.Forms.Control.CreateControl()
at System.Windows.Forms.Control.WmShowWindow(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at System.Windows.Forms.Form.WmShowWindow(Message& m)
at System.Windows.Forms.Form.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, WM msg, IntPtr wparam, IntPtr lparam)
This exception was originally thrown at this call stack:
System.Windows.Forms.BindingSource.AddNew()
System.Windows.Forms.CurrencyManager.AddNew()
System.Windows.Forms.RelatedCurrencyManager.ParentManager_CurrentItemChanged(object, System.EventArgs)
System.Windows.Forms.RelatedCurrencyManager.Bind(System.Windows.Forms.BindingManagerBase, string)
System.Windows.Forms.BindingContext.EnsureListManager(object, string)
System.Windows.Forms.DataGridView.DataGridViewDataConnection.SetDataConnection(object, string)
System.Windows.Forms.DataGridView.DataMember.set(string)
Deleteme.Form1.Form1_Load(Object, System.EventArgs) in Form1.vb
System.Windows.Forms.Form.OnLoad(System.EventArgs)
System.Windows.Forms.Form.OnCreateControl()
...
[Call Stack Truncated]
If Parent has a record, and only Child and Grandchild not, there is no error. The error is specifically when there are three generations. (The example below is part of a larger example, with more details in a comment.)
Expected behavior:
No error.
Minimal repro:
New vb winforms project, replace Form1 with:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim Data As New DataSet
Dim Dgv As New DataGridView
Controls.Add(Dgv)
Data.Tables.Add(New DataTable("Parent"))
Data.Tables("Parent").Columns.Add("Id")
Data.Tables.Add(New DataTable("Child"))
Data.Tables("Child").Columns.Add("Id")
Data.Tables.Add(New DataTable("Grandchild"))
Data.Tables("GrandChild").Columns.Add("Id")
' Uncomment for no error.
'Data.Tables("Parent").Rows.Add(1)
Data.Relations.Add(New DataRelation("Parent_Child", Data.Tables("Parent").Columns("Id"), Data.Tables("Child").Columns("Id")))
Data.Relations.Add(New DataRelation("Child_Grandchild", Data.Tables("Child").Columns("Id"), Data.Tables("Grandchild").Columns("Id")))
Dgv.DataSource = New BindingSource With {.DataSource = Data, .DataMember = "Parent"}
Dgv.DataMember = "Parent_Child.Child_Grandchild"
End Sub
End Class
Issue Analytics
- State:
- Created 3 years ago
- Comments:36 (22 by maintainers)
Top Results From Across the Web
c# - System.InvalidOperationException: rows cannot be ...
System.InvalidOperationException: rows cannot be programmatically added to the datagridview's rows collection when the control is data-bound.
Read more >How to bind three datagridviews together as parent, child ...
I want to click on a record in parent and have the related records show up in child, and then child's related records...
Read more >Access Objects Bound to DataGridView Rows
Learn how to access objects bound to Windows Forms DataGridView rows to display a table of information stored in a collection of business ......
Read more >DataGridView.DataBindingComplete Event
This event is raised when the contents of the data source change or when the value of the DataSource, DataMember, or BindingContext property...
Read more >[Solved] How can I add rows to a datagridview while ...
"System.InvalidOperationException: 'Rows cannot be programmatically added to the DataGridView's rows collection when the control is data-bound."
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
By doing it the same way you are doing it currently, by sharing the data source. Each data source (be it implicitly generated or explicitly) has a “current” record. Thats why I said earlier
Binding sources are “components” which are similar to controls, they are supposed to be shared, not objects you construct to pass data and then throw away. Technically you are even supposed to keep them arround and dispose them later (I don’t know if it has any ill effect not doing so, assuming the form doesn’t outlive the grids I’d expect the garbage collector to clean up after you.)
Does this achieve what you are looking for or am I still missing some detail? Clicking a row in any grid seems to change the dependent grids appropriately as expected for binding sources.
Applied the workaround applied and was able to run the code. Thank you for all the help in getting thus far!