Cannot add row to DataGridView based on array

A

Andrus

I need to add row in DatagridView based on array of business entities.
I used AddingNew event as described in Joe Stegman "DataBinding FAQ -
Updated.doc" from Microsoft without success.
Error "Collection is read only" occurs.

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<Customer> list = new Customer[0];
BindingList<Customer> bindingList = new BindingList<Customer>(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()
*/
 
G

Guest

Hello,
Here the code you wrote IList<Customer> list = new Customer[0]; the code
use the System.Array, Add does not support by the Array class.

Here the code from the reflector :
int IList.Add(object value)
{
throw new
NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
}

So, use an explicit list as : ArrayList, List<T> .. .

Goodluck.


--
Sincerely
Yaron Karni
http://dotnetbible.blogspot.com/


Andrus said:
I need to add row in DatagridView based on array of business entities.
I used AddingNew event as described in Joe Stegman "DataBinding FAQ -
Updated.doc" from Microsoft without success.
Error "Collection is read only" occurs.

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<Customer> list = new Customer[0];
BindingList<Customer> bindingList = new BindingList<Customer>(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()
*/
 
A

Andrus

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<T>
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<T> or some of its implementation can maintain
separate list of added objects by implementing custom Add() method.


Andrus.


Yaron Karni said:
Hello,
Here the code you wrote IList<Customer> list = new Customer[0]; the code
use the System.Array, Add does not support by the Array class.

Here the code from the reflector :
int IList.Add(object value)
{
throw new
NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
}

So, use an explicit list as : ArrayList, List<T> .. .

Goodluck.


--
Sincerely
Yaron Karni
http://dotnetbible.blogspot.com/


Andrus said:
I need to add row in DatagridView based on array of business entities.
I used AddingNew event as described in Joe Stegman "DataBinding FAQ -
Updated.doc" from Microsoft without success.
Error "Collection is read only" occurs.

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<Customer> list = new Customer[0];
BindingList<Customer> bindingList = new BindingList<Customer>(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()
*/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top