Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Clarifying Usage of AddingNew with BindingSource

1,350 views
Skip to first unread message

Daniel Grassick

unread,
Dec 6, 2006, 3:34:02 PM12/6/06
to
Daniel Herling of Microsoft says “BindingSource AddingNew does not work when
the BindingSource is bound to a DataTable” in a reply to “MSDN Forums »
Windows Forms » Windows Forms Data Controls and Databinding » BindingSource
AddingNew”. However, Linda Liu, Microsoft Online Community Support implies it
does work in her reply to “DataGridView Adding Rows” by “Chuck P” in the
managed newsgroups.

I originally wanted to use AddingNew to set default values for a table row
when the Add New button is clicked in the BindingNavigator but I have
switched to setting dataset table defaults as suggested by Daniel Herling and
also Lind Liu. I would still like to know if what Daniel said was true or if
there is a way to create a new table row in the AddingNew event.

I created a simple example using an SQL Server table named “TestTable” with
an identity column called “TestID” and a “varchar(25)” column called
“TestText”. I used standard drap and drop operations to create a C# windows
form with a DataGridView bound to my test table and as usual a
BindingNavigator was automatically created. I renamed the generated UI
objects but the only code I wrote was for the event handler for the AddingNew
event for the generated BindingSource as follows:

DataRowView rowView = mctlTestDataSet.TestTable.DefaultView.AddNew();
TestDataSet.TestTableRow newRow = (TestDataSet.TestTableRow)rowView.Row;
newRow.TestText = "<New>";
e.NewObject = rowView;

I took me quite a while to come up with this code and I am wondering if it
is “correct” but the operation is not support for a bound DataTable. Clicking
on the BindingNavigator Add New button results in System.ArgumentException
“Cannot add external objects to this list.”

I hope you can satisfy my curiousity and help me understand the issues. I
would also be interested in a solution that disconnects the Add New button
from the BindingNavigator and uses a custom clidk event to directly add a new
row to the underlying data table.

Thanks for your help,
Daniel Grassick

Linda Liu [MSFT]

unread,
Dec 7, 2006, 3:32:09 AM12/7/06
to
Hi Daniel,

The AddingNew event occurs before a new object is added to the underlying
list represented by the List property. This event is fired after the AddNew
method is called, but before the new item is created and added to the
underlying list. By handling this event, the programmer can provide custom
item creation and insertion behavior without being forced to derive from
the BindingSource class. This is accomplished in the event handler by
setting the NewObject property of the
System.ComponentModel.AddingNewEventArgs parameter to the new item.

Note that you CANNOT set the NewObject property when bound to a DataView or
DataTable because you cannot add a new DataRowView to the list.

Sorry that I didn't make it clear in my reply to the thread 'DataGridView
Adding Rows'. I meant that we could handle the AddingNew event of the
BindingSource component to specify the default value of the new object,
when the data source is a list of business objects.

If you'd like to write code to add a new row in the underlying data source,
you could call the AddNew method of the BindingSource, or the AddNew method
of the BindingManagerBase object associated with the data source, in this
case, BindingSource.

The following is a sample.

this.BindingContext[this.bindingSource1].AddNew();
--or--
this.bindingSource1.CurrencyManager.AddNew();

When you edit data in DataTable in your program, I don't suggest that you
add a row into the DataTable directly, because it would bring some problems
of row version and UI update, if you have used a BindingSource component
and bind the DataGridView to the BindingSource component.

Hope this helps.
If you have anything unclear, please feel free to let me know.


Sincerely,
Linda Liu
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.

Bart Mermuys

unread,
Dec 7, 2006, 6:34:57 AM12/7/06
to
Hi Linda,

"Linda Liu [MSFT]" <v-l...@online.microsoft.com> wrote in message
news:m5nrDpdG...@TK2MSFTNGHUB02.phx.gbl...


> Hi Daniel,
>
> The AddingNew event occurs before a new object is added to the underlying
> list represented by the List property. This event is fired after the
> AddNew
> method is called, but before the new item is created and added to the
> underlying list. By handling this event, the programmer can provide custom
> item creation and insertion behavior without being forced to derive from
> the BindingSource class. This is accomplished in the event handler by
> setting the NewObject property of the
> System.ComponentModel.AddingNewEventArgs parameter to the new item.
>
> Note that you CANNOT set the NewObject property when bound to a DataView
> or
> DataTable because you cannot add a new DataRowView to the list.

Actually you can set it when bound to a DataSet/DataTable/DataView.

In this case BindingSource.List is a DataView, and if you do
((DataView)BindingSouce.List).AddNew inside the AddingNew eventhandler, then
the BindingSource will see that the List.Count already increased and it
won't try to add the item (e.NewObject) to the List (it's already added).

Greetings

Bart Mermuys

unread,
Dec 7, 2006, 6:35:10 AM12/7/06
to
Hi,

"Daniel Grassick" <dmg...@community.nospam> wrote in message
news:5D761904-D345-4682...@microsoft.com...

When you set e.NewObject to something other then null, then one of two
things can happen:

- if the BindingSource.List.Count was increased during the eventhandler then
it won't add e.NewObject to the list

- if the BindingSource.List.Count wasn't increased then it will add
e.NewObject to the list.

In your case, it shouldn't add e.NewObject to the list, the DataRowView is
already added because of the DataView.AddNew.

BUT, the error you are having suggests that the BindingSource is actually
trying to add the DataRowView. So it doesn't see the increase in
BindingSource.List.Count and what can cause that ? You calling AddNew on a
different DataView then the one the BindingSource is refering.

You used standard drap and drop which means that the
BindingSource.DataSource is set to a DataSet which also means that
BindingSource.List isn't using the DefaultView. To get the right DataView,
cast BindingSource.List, eg.:

DataRowView rowView = ((DataView)yourBindingSource.List).AddNew();


TestDataSet.TestTableRow newRow = (TestDataSet.TestTableRow)rowView.Row;
newRow.TestText = "<New>";

e.NewObject = rowView;


When you don't handle the AddingNew event and the BindingSource adds the new
row (also using DataView.AddNew) then it will also position the current
record to the new row, like so:
yourBindingSource.Position = yourBindingSource.Count - 1;


While it can work, i still prefer to use DataTable.TableNewRow event to set
defaults.

>
> I took me quite a while to come up with this code and I am wondering if it
> is "correct" but the operation is not support for a bound DataTable.
> Clicking
> on the BindingNavigator Add New button results in System.ArgumentException
> "Cannot add external objects to this list."
>
> I hope you can satisfy my curiousity and help me understand the issues.

> I
> would also be interested in a solution that disconnects the Add New button
> from the BindingNavigator and uses a custom clidk event to directly add a
> new
> row to the underlying data table.

Just set BindingNavigator.DeleteItem to null (designer) and then double
click the Delete button, then you can have a custom handler.

But adding a DataRow directly to the DataTable isn't the same as calling
AddNew on the DataView. Calling AddNew on the DataView keeps the row in an
edited state which allows the user to cancel the new row (eg DataGridView
ESC) and it also postpones sorting until the row is end editing (when the
user browses to another row or endedit is explicitly called).


HTH,
Greetings

Linda Liu [MSFT]

unread,
Dec 7, 2006, 11:36:46 PM12/7/06
to
Hi Bart,

Thank you for pointing it out.

Linda Liu [MSFT]

unread,
Dec 8, 2006, 3:09:05 AM12/8/06
to
Hi Daniel,

I performed a test based on what Bart has suggested and confirmed it works.

In fact, when we call BindingSource.AddNew method to add a new row into the
underlying data table, BindingSource component internally calls
'(DataView)yourBindingSource.List).AddNew()' to do the actual work.

Generally speaking, the common usage of BindingSource's AddingNew event is
to create a new object with the same type as the objects in the
BindingSource.List, and set the new object to the NewObject property of the
AddingNewEventArgs parameter.

When we bind a BindingSource component to a DataTable, the BindingSource
component is actually bound to a DataView. The problem is that we could not
add a DataRowView instance to a DataView, except that we call
DataView.AddNew method to do it.

What Bart said about BindingSource e.NewObject to the list seems right. As
Bart has mentioned, one problem of the workaround is that the current row
is not set the new row after the new row is added. To solve the problem,
set the Position property of the BindingSource to the value of
BindingSource.Count -1.

Hope this helps.
If you have anything unclear, please feel free to let me know.

0 new messages