Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Windows Forms / WinForm Controls / February 2007

Tip: Looking for answers? Try searching our database.

Datagridview.datasource triggers RowsAdded event twice

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Patrik - 19 Feb 2007 08:35 GMT
Hi,

I am binding a datatable to the datasource of a datagridview. I have noticed
that this fires the RowsAdded event twice. I have noticed that because I use
the method RowsAdded to do some stuff and this method is called twice.

Any clue why this happens?
ClayB - 19 Feb 2007 10:14 GMT
In a simple example where the new rows were being added through the
grid's UI (typing into the AddNew row), the RowsAdded event was only
hit once for me.

If you are using C#, you might put a stop on the line where you
subscribe to the event to see if it is being hit twice fro some
reason. If you are using VB and have a AddHandler line subscribing to
the event, you might check to see if that line is being hit twice (or
if you also have a Handles clause on the function itself).

===============
Clay Burch
Syncfusion, Inc.
Patrik - 19 Feb 2007 11:20 GMT
I am writing a C# application and I have a usercontrol with 3 datagridviews
in it. I have connected the RowsAdded event to one of the grids in design
mode so the designer code automatically created handles the subscription.The
subscription is only hit once but the method is called twice for some
reason. I can not understand why.

I am populating the items for a combobox in the method (the column is a
ComboboxColumn). I do that for each row because the items in the combobox
should be different for each row.

/Patrik

> In a simple example where the new rows were being added through the
> grid's UI (typing into the AddNew row), the RowsAdded event was only
[quoted text clipped - 9 lines]
> Clay Burch
> Syncfusion, Inc.
Jeffrey Tan[MSFT] - 20 Feb 2007 02:24 GMT
Hi Patrik,

Thanks for your feedback!

Based on my understanding, your further test confirms that the
DataGridView.RowsAdd event is only fired once(The subscription is only hit
once). Can you tell me which method is called twice(but the method is
called twice)?

Is it possible for you to create a little sample project to help us
reproduce your problem? Once I can reproduce it locally, I will perform
some debugging and research in it.

Thanks.

Best regards,
Jeffrey Tan
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.
Patrik - 20 Feb 2007 08:13 GMT
Hi,

I have a Form with one Datagridview on it. I create two columns in design
time and set the DataPropertyName to "Name" and "Value" that is the names of
the columns in the dataTable that i bind to. I used the the Loads event of
the form to fill the dataSet and bind it to the DataGridView. Then I also
subscribe to th event RowsAdded (I do this connection in design time) and
just makes a Debug.WriteLine there. The output shows that this method is run
twice. Below you can see the code I used.

Please let me know if  I am doing something wrong. /Patrik
namespace TestRowsAdded

{

     public partial class Form1 : Form

    {

          DataSet m_DataSet;

          public Form1()

          {

                 InitializeComponent();

           }

           private void Form1_Load(object sender, EventArgs e)

          {

                  FillDataSet();

                  m_DataGridView.AutoGenerateColumns = false;

                  m_DataGridView.DataSource = m_DataSet.Tables["table1"];

           }

            private void FillDataSet()

            {

                  m_DataSet = new DataSet();

                  DataTable table = new DataTable("table1");

                  DataColumn column = new DataColumn("Name",
typeof(string));

                  table.Columns.Add(column);

                 column = new DataColumn("Value", typeof(string));

                 table.Columns.Add(column);

                 DataRow row;

                 for(int i = 0; i < 10; i++)

                {

                     row = table.NewRow();

                     row["Name"] = "item " + i.ToString();

                     row["Value"] = i.ToString();

                     table.Rows.Add(row);

                 }

                 m_DataSet.Tables.Add(table);

         }

         private void m_DataGridView_RowsAdded(object sender,
DataGridViewRowsAddedEventArgs e)

         {

                for(int rowCount = e.RowIndex; rowCount < e.RowIndex +
e.RowCount; rowCount++)

               {

                    string message = string.Format("Row number {0}
added",rowCount);

                    Debug.WriteLine(message);

               }

         }

    }

}

> Hi Patrik,
>
[quoted text clipped - 33 lines]
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
Jeffrey Tan[MSFT] - 20 Feb 2007 09:16 GMT
Hi Patrik,

Thanks for your feedback!

Yes, I have followed your steps to setup the databinding and I construct
the datatable manually like below:
private void Form1_Load(object sender, EventArgs e)
{
   DataTable dt = new DataTable();
   dt.Columns.Add(new DataColumn("value", typeof(int)));
   dt.Columns.Add(new DataColumn("name", typeof(string)));

   for (int i = 0; i < 5; i++)
   {
       DataRow dr = dt.NewRow();
       dr["value"] = i;
       dr["name"] = "item" + i.ToString();
       dt.Rows.Add(dr);
   }
   this.dataGridView1.DataSource = dt;

}

private void dataGridView1_RowsAdded(object sender,
DataGridViewRowsAddedEventArgs e)
{
   System.Diagnostics.Debug.WriteLine("Row added: " +
e.RowIndex.ToString());
}
It seems that "RowsAdded" event is called mutiple times with e.RowIndex
mostly equals "0". More strangely, I only add one row into the DataTable
like below:
for (int i = 0; i < 1; i++)
{
   DataRow dr = dt.NewRow();
   dr["value"] = i;
   dr["name"] = "item" + i.ToString();
   dt.Rows.Add(dr);
}
It will strill trigger this event 8 times with e.RowIndex always "0":

Row added: 0
Row added: 0
Row added: 0
Row added: 0
Row added: 0
Row added: 0
Row added: 0
Row added: 0

So it seems RowsAdded event is not reliable during form load databinding,
but based on my test, it will only be called once if you manually add a new
row through editing the bottom "new row" in DataGridView.

I will try to contact Winform dev team for this issue and hope they can
provide some comment on this issue. I will feedback any progress here ASAP.
Thanks.

Best regards,
Jeffrey Tan
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.
ClayB - 20 Feb 2007 12:43 GMT
You could wrap your DataTable in a BindingSource object and then
listen to the BindingSource.ListChanged event (or the AddingNew event)
for ListChangedType.ItemAdded to catch (only once) the adding of new
rows to the DataTable. (Or, you could access the CurrecnyManager.List
for this bindingcontext and listen to its ListChanged event, but this
you could not do from the designer).

Here is the code changes in you sample to show this (I think you can
also do it from the designer as well.)

private BindingSource src;

...//in Form_Load
dataGridView1.DataSource = this.src;

...//in FillDataSet()
          DataTable table = new DataTable("table1");
           this.src = new BindingSource();
           src.DataSource = table;
           src.ListChanged += new
ListChangedEventHandler(src_ListChanged);

void src_ListChanged(object sender, ListChangedEventArgs e)
{
   if (e.ListChangedType == ListChangedType.ItemAdded)
   {
       Console.WriteLine(string.Format("added {0}", e.NewIndex));
   }
}

===================
Clay Burch
Syncfusion, Inc.
Patrik - 20 Feb 2007 14:33 GMT
The dataTable is populated as start of the program using a xml-file and
MSDataSetGenerator. Later when entering a specific view I will bind a
datagridview to that table. Why I need to use the RowsAdded event is that I
need to populate a combox column that will have items that are unique for
ech cell in that column.

So as I understand it the Bindingsource will react when I populate the
dataTable which happens at start of the program. Later when entering a
specific view I bind these values to a gridView and react to the RowsAdded
to be able to populate the combobox for each row. So the data i get from the
dataTable shall be the SelectedItem for the combobox.

/Patrik

> You could wrap your DataTable in a BindingSource object and then
> listen to the BindingSource.ListChanged event (or the AddingNew event)
[quoted text clipped - 29 lines]
> Clay Burch
> Syncfusion, Inc.
Jeffrey Tan[MSFT] - 22 Feb 2007 04:13 GMT
Hi Patrik,

Sorry for the late response, I am out of office at home yesterday.

I finally contacted one development lead of .Net Winform team, and below is
his comment:

During databinding, the "new row" at the bottom gets added and removed
several times - this adds some instances of the RowsAdded events.  You
could prevent this by setting
this.dataGridView1.AllowUserToAddRows = false;
in the designer.cs file.

When you use this code:
       private void Form1_Load(object sender, EventArgs e)
       {
           System.Diagnostics.Debug.WriteLine("Form1 Load start");
           DataTable dt = new DataTable();
           dt.Columns.Add(new DataColumn("value", typeof(int)));
           dt.Columns.Add(new DataColumn("name", typeof(string)));

           for (int i = 0; i < 1; i++)
           {
               DataRow dr = dt.NewRow();
               dr["value"] = i;
               dr["name"] = "item" + i.ToString();
               dt.Rows.Add(dr);
           }
           System.Diagnostics.Debug.WriteLine("Form1 Load - setting
DataSource");
           this.dataGridView1.DataSource = dt;
           System.Diagnostics.Debug.WriteLine("Form1 Load - setting
AllowUserToAddRows");
           this.dataGridView1.AllowUserToAddRows = true;
           System.Diagnostics.Debug.WriteLine("Form1 Load done");
       }

       private void dataGridView1_RowsAdded(object sender,
DataGridViewRowsAddedEventArgs e)
       {
           System.Diagnostics.Debug.WriteLine("Rows added: e.RowIndex=" +
e.RowIndex.ToString() + ", e.RowCount=" + e.RowCount.ToString());
       }

       private void dataGridView1_DataBindingComplete(object sender,
DataGridViewBindingCompleteEventArgs e)
       {
           System.Diagnostics.Debug.WriteLine("DataBindingComplete event
triggered");
       }

       private void dataGridView1_RowsRemoved(object sender,
DataGridViewRowsRemovedEventArgs e)
       {
           System.Diagnostics.Debug.WriteLine("Row removed: " +
e.RowIndex.ToString());
       }

       private void dataGridView1_DataSourceChanged(object sender,
EventArgs e)
       {
           System.Diagnostics.Debug.WriteLine("DataSourceChanged event
triggered");
       }

       private void dataGridView1_DataMemberChanged(object sender,
EventArgs e)
       {
           System.Diagnostics.Debug.WriteLine("DataMemberChanged event
triggered");
       }

You get this output:

   Form1 Load start
   Form1 Load - setting DataSource
   Rows added: e.RowIndex=0, e.RowCount=1
   DataBindingComplete event triggered
   Row removed: 0
   Rows added: e.RowIndex=0, e.RowCount=1
   DataSourceChanged event triggered
   DataBindingComplete event triggered
   Form1 Load - setting AllowUserToAddRows
   Rows added: e.RowIndex=1, e.RowCount=1
   Form1 Load done

First DataBindingComplete event raised:
>   
WindowsApplication13.exe!WindowsApplication13.Form1.dataGridView1_DataBindin
gComplete(object sender = {System.Windows.Forms.DataGridView},
System.Windows.Forms.DataGridViewBindingCompleteEventArgs e =
{System.Windows.Forms.DataGridViewBindingCompleteEventArgs}) Line 49    C#
   
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.OnDataBindingComp
lete(System.Windows.Forms.DataGridViewBindingCompleteEventArgs e =
{System.Windows.Forms.DataGridViewBindingCompleteEventArgs}) Line 14964 +
0xd bytes    C#
   
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.OnDataBindingComp
lete(System.ComponentModel.ListChangedType listChangedType = Reset) Line
14955 + 0x22 bytes    C#
   
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.OnBindingContextC
hanged(System.EventArgs e = {System.EventArgs}) Line 11563 + 0xa bytes    C#
   
System.Windows.Forms.dll!System.Windows.Forms.Control.OnParentBindingContext
Changed(System.EventArgs e = {System.EventArgs}) Line 8105 + 0xc bytes    C#
   
System.Windows.Forms.dll!System.Windows.Forms.Control.OnBindingContextChange
d(System.EventArgs e = {System.EventArgs}) Line 7829 + 0x1d bytes    C#
   
System.Windows.Forms.dll!System.Windows.Forms.Control.BindingContextInternal
.set(System.Windows.Forms.BindingContext value =
{System.Windows.Forms.BindingContext}) Line 1265 + 0x10 bytes    C#
   
System.Windows.Forms.dll!System.Windows.Forms.Control.BindingContext.set(Sys
tem.Windows.Forms.BindingContext value =
{System.Windows.Forms.BindingContext}) Line 1284 + 0x9 bytes    C#
   
System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.BindingContex
t.set(System.Windows.Forms.BindingContext value =
{System.Windows.Forms.BindingContext}) Line 255 + 0xa bytes    C#
   
System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.BindingContex
t.get() Line 250 + 0xc bytes    C#
   
System.Windows.Forms.dll!System.Windows.Forms.Control.BindingContextInternal
.get() Line 1248 + 0xa bytes    C#
   
System.Windows.Forms.dll!System.Windows.Forms.Control.BindingContext.get()
Line 1281 + 0x7 bytes    C#
   
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.DataGridViewDataC
onnection.SetDataConnection(object dataSource = {}, string dataMember = "")
Line 1147 + 0xe bytes    C#
   
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.DataSource.set(ob
ject value = {}) Line 2418 + 0x28 bytes    C#
    WindowsApplication13.exe!WindowsApplication13.Form1.Form1_Load(object
sender = {WindowsApplication13.Form1, Text: Form1}, System.EventArgs e =
{System.EventArgs}) Line 36 + 0x12 bytes    C#

Second DataBindingComplete event raised:
>   
WindowsApplication13.exe!WindowsApplication13.Form1.dataGridView1_DataBindin
gComplete(object sender = {System.Windows.Forms.DataGridView},
System.Windows.Forms.DataGridViewBindingCompleteEventArgs e =
{System.Windows.Forms.DataGridViewBindingCompleteEventArgs}) Line 49    C#
   
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.OnDataBindingComp
lete(System.Windows.Forms.DataGridViewBindingCompleteEventArgs e =
{System.Windows.Forms.DataGridViewBindingCompleteEventArgs}) Line 14964 +
0xd bytes    C#
   
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.OnDataBindingComp
lete(System.ComponentModel.ListChangedType listChangedType = Reset) Line
14955 + 0x22 bytes    C#
   
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.OnDataSourceChang
ed(System.EventArgs e = {System.EventArgs}) Line 15276 + 0x9 bytes    C#
   
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.DataSource.set(ob
ject value = {}) Line 2433 + 0x10 bytes    C#
    WindowsApplication13.exe!WindowsApplication13.Form1.Form1_Load(object
sender = {WindowsApplication13.Form1, Text: Form1}, System.EventArgs e =
{System.EventArgs}) Line 36 + 0x12 bytes    C#

The customer may want to use the DataSourceChanged or DataBindingComplete
events initially and then RowsAdded / RowRemoved later on, using some sort
of internal flag.

When 5 rows are added instead of 1, you get this output:

   Form1 Load begining
   Form1 Load - setting DataSource
   Rows added: e.RowIndex=0, e.RowCount=1
   Rows added: e.RowIndex=1, e.RowCount=4
   DataBindingComplete event triggered
   Row removed: 0
   Rows added: e.RowIndex=0, e.RowCount=1
   Rows added: e.RowIndex=1, e.RowCount=4
   DataSourceChanged event triggered
   DataBindingComplete event triggered
   Form1 Load - setting AllowUserToAddRows
   Rows added: e.RowIndex=5, e.RowCount=1
   Form1 Load done

So you may use DataSourceChanged event to enumerate all the rows and
generate the combobox in each row during initial form_loading. In this
period, you may suppress the using of RowAdded event through an internal
flag. After setting AllowUserToAddRows property to true and last RowAdded
event goes through, you may toggle that internal flag to use RowAdded event
in the life time of the application. I hope this logic makes sense to you.

Thanks.

Best regards,
Jeffrey Tan
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.
Patrik - 26 Feb 2007 07:01 GMT
Thank you Jefferey for your reply!

> Hi Patrik,
>
[quoted text clipped - 217 lines]
> This posting is provided "AS IS" with no warranties, and confers no
> rights.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.