I need to add row in DatagridView based on array of business entities.
Error "Collection is read only" occurs.
I'm using NHibernate.
NHiberante returns array of business objects.
So my source type is System.Array and I cannot change it.
Joe Stegman "DataBinding FAQ - Updated.doc" describes that BindingList
AddingNew event should be used in this case.
Also there is CoreAddNew method which is not documented in VCS 2005 Express
documentation.
I expect that BindingList or some of its implementation can maintain
separate list of added objects by implementing custom Add() method.
How to fix ?
Andrus.
Using .NET 2.
Code to reproduce:
using System.Windows.Forms;
using System.Collections.Generic;
using System.ComponentModel;
class TestApplication {
static void Main() { Application.Run(new TestForm()); }
}
class TestForm : Form {
DataGridView DataGridView = new DataGridView();
public TestForm() {
Controls.Add(DataGridView);
BindingSource BindingSource = new BindingSource();
IList list = new Customer[0];
BindingList bindingList = new BindingList(list);
BindingSource.DataSource = bindingList;
BindingSource.AddingNew += delegate(object sender, AddingNewEventArgs e) {
e.NewObject = new Customer();
};
DataGridView.DataSource = BindingSource;
}
}
class Customer {
string name;
public string Name {
get { return name; }
set { name = value; }
}
}
Observed:
System.NotSupportedException was unhandled
Message="Collection is read-only."
Source="mscorlib"
StackTrace:
at System.ThrowHelper.ThrowNotSupportedException(ExceptionResource resource)
at System.Collections.ObjectModel.Collection`1.System.Collections.IList.Add(Object value)
at System.Windows.Forms.BindingSource.Add(Object value)
at System.Windows.Forms.BindingSource.AddNew()
at System.Windows.Forms.CurrencyManager.AddNew()
at System.Windows.Forms.DataGridView.DataGridViewDataConnection.AddNew()
at System.Windows.Forms.DataGridView.DataGridViewDataConnection.OnNewRowNeeded()
at System.Windows.Forms.DataGridView.OnRowEnter(DataGridViewCell& dataGridViewCell, Int32 columnIndex, Int32 rowIndex, Boolean canCreateNewRow, Boolean validationFailureOccurred)
at System.Windows.Forms.DataGridView.SetCurrentCellAddressCore(Int32 columnIndex, Int32 rowIndex, Boolean setAnchorCellAddress, Boolean validateCurrentCell, Boolean throughMouseClick)
at System.Windows.Forms.DataGridView.SetAndSelectCurrentCellAddress(Int32 columnIndex, Int32 rowIndex, Boolean setAnchorCellAddress, Boolean validateCurrentCell, Boolean throughMouseClick, Boolean clearSelection, Boolean forceCurrentCellSelection)
at System.Windows.Forms.DataGridView.MakeFirstDisplayedCellCurrentCell(Boolean includeNewRow)
at System.Windows.Forms.DataGridView.OnEnter(EventArgs e)
at System.Windows.Forms.Control.NotifyEnter()
at System.Windows.Forms.ContainerControl.UpdateFocusedControl()
at System.Windows.Forms.ContainerControl.AssignActiveControlInternal(Control value)
at System.Windows.Forms.ContainerControl.ActivateControlInternal(Control control, Boolean originator)
at System.Windows.Forms.ContainerControl.SetActiveControlInternal(Control value)
at System.Windows.Forms.ContainerControl.SetActiveControl(Control ctl)
at System.Windows.Forms.ContainerControl.set_ActiveControl(Control value)
at System.Windows.Forms.Control.Select(Boolean directed, Boolean forward)
at System.Windows.Forms.Control.SelectNextControl(Control ctl, Boolean forward, Boolean tabStopOnly, Boolean nested, Boolean wrap)
at System.Windows.Forms.Control.SelectNextControlInternal(Control ctl, Boolean forward, Boolean tabStopOnly, Boolean nested, Boolean wrap)
at System.Windows.Forms.Form.set_Active(Boolean value)
at System.Windows.Forms.Form.WmActivate(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.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.SafeNativeMethods.ShowWindow(HandleRef hWnd, Int32 nCmdShow)
at System.Windows.Forms.Control.SetVisibleCore(Boolean value)
at System.Windows.Forms.Form.SetVisibleCore(Boolean value)
at System.Windows.Forms.Control.set_Visible(Boolean value)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at TestApplication.Main() in C:\test\test\Program.cs:line 20
at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
Andrus