DataGrid bug?

  • Thread starter Tsviatko Yovtchev
  • Start date
T

Tsviatko Yovtchev

I am attaching a DataTable to the DataSource of a DataGrid control. When
I try to delete rows from the DataTable:

if(i < ((DataTable)dataGridMain.DataSource).Rows.Count || i > 0)
((DataTable)dataGridMain.DataSource).Rows.RemoveAt(i);

under certain conditions I get ArgumentOutOfRange exception. I get the
exception if and only if the selected cell in the DataGrid was changed
one or more times before the delete operation. If the selected cell has
not been changed the code above executes smoothly.

I seriously begin to think that this is a bug in the .NET CF. It is
apparent that the variable i cannot be out of range so what is that
exception supposed to mean?
 
T

Tsviatko Yovtchev

under certain conditions I get ArgumentOutOfRange exception. I get the
exception if and only if the selected cell in the DataGrid was changed
one or more times before the delete operation. If the selected cell has
not been changed the code above executes smoothly.

I just discovered that the selected cell should be changed across the
different columns for the ArgumetnOutOfRangeException to get thrown. If
cells at different rows in the same column are selected everything runs
fine.
 
T

Tsviatko Yovtchev

Sergey said:

Well, the info in this thread sounds reasonable. However, I apply no
filtering whatsoever so the row indexes in the DataGrid should match the
indexes in the DataTable. To be on the safe side I did try the following:


for(int i = 0; i < ((DataTable)dataGridMain.DataSource).Rows.Count; )
if(dataGridMain.IsSelected(i))
{
((DataTable)dataGridMain.DataSource).DefaultView.Delete(i);
}

but I am still getting the exception under the conditions I specified in
my previous post(I get the exception if and only if the selected cell in
the DataGrid was changed ACROSS DIFFERENT COLUMNS one or more times
before the delete operation. If the selected cell has not been changed
the code above executes smoothly). So, I still keep on thinking it is a
bug in the .NET CF since if there was a real problem with the indexes
the code above would always throw an exception which it does not.
--
Sergey Bogdanov [.NET CF MVP, MCSD]
http://www.sergeybogdanov.com


Tsviatko said:
I am attaching a DataTable to the DataSource of a DataGrid control.
When I try to delete rows from the DataTable:

if(i < ((DataTable)dataGridMain.DataSource).Rows.Count || i > 0)
((DataTable)dataGridMain.DataSource).Rows.RemoveAt(i);

under certain conditions I get ArgumentOutOfRange exception. I get the
exception if and only if the selected cell in the DataGrid was changed
one or more times before the delete operation. If the selected cell
has not been changed the code above executes smoothly.

I seriously begin to think that this is a bug in the .NET CF. It is
apparent that the variable i cannot be out of range so what is that
exception supposed to mean?
 
I

Ilya Tumanov [MS]

DataGrid has it share of bugs (all known fixed in NETCF V2), but this
problem is not one of them. Rather your code is based on wrong assumptions
and it's not supposed to work.



First of all, you've assumed number of rows in the DataTable is the same as
number of rows in the DataView/DataTable. You can compare these in a loop to
find our that's not the case even though you're not using filtering and
sorting. Indexes also can't possibly be the same since number of rows is
different.



Next wrong assumption is what row indexes in the DataGrid would not change
while this loop is executed.

That is also not the case as indexes would change as soon as first row is
deleted:



I=1, so far so good. About to delete selected row:



I DataGrid DataView DataTable

0 1 1 1
1 2 2 2 --------
Selected

2 3 3 3 -------- Selected

3 4 4 4



After first delete you've got into total mess (I'm assuming you're
incrementing 'i' at the end of loop):



I=2, row just deleted row @1:



I DataGrid DataView DataTable

0 1 1 1

1 3 3 2 -------- Row is in
deleted state in DT, selected in DG/DV and they are different rows.
2 4 4 3 -------- Row
indexes out of sync now.

4 4



Note you would skip row '3' because it would move to index 1 you've already
processed. Also now you have 4 rows in the DataTable (one in deleted state)
and only 3 of them in the DataView/DataTable. Inevitably you would increment
row index to 3 which would generate an exception.



Let's try it another way:



DataView dv = (DataTable)dataGridMain.DataSource.DefaultView;



for (int i = 0; i < dv.Count; i++) // Never use DataTable with
DataGrid indexes directly, only use DataView

{

if(dataGridMain.IsSelected(i))

{

dv.Delete(i);



i = 0; // Restart
enumeration as deletion above moved rows making our index invalid.

}

}


--
Best regards,

Ilya

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

*** Want to find answers instantly? Here's how... ***

1. Go to
http://groups-beta.google.com/group/microsoft.public.dotnet.framework.compactframework?hl=en
2. Type your question in the text box near "Search this group" button.
3. Hit "Search this group" button.
4. Read answer(s).

Tsviatko Yovtchev said:
Sergey said:

Well, the info in this thread sounds reasonable. However, I apply no
filtering whatsoever so the row indexes in the DataGrid should match the
indexes in the DataTable. To be on the safe side I did try the following:


for(int i = 0; i < ((DataTable)dataGridMain.DataSource).Rows.Count; )
if(dataGridMain.IsSelected(i))
{ ((DataTable)dataGridMain.DataSource).DefaultView.Delete(i);
}

but I am still getting the exception under the conditions I specified in
my previous post(I get the exception if and only if the selected cell in
the DataGrid was changed ACROSS DIFFERENT COLUMNS one or more times before
the delete operation. If the selected cell has not been changed the code
above executes smoothly). So, I still keep on thinking it is a bug in the
.NET CF since if there was a real problem with the indexes the code above
would always throw an exception which it does not.
--
Sergey Bogdanov [.NET CF MVP, MCSD]
http://www.sergeybogdanov.com


Tsviatko said:
I am attaching a DataTable to the DataSource of a DataGrid control. When
I try to delete rows from the DataTable:

if(i < ((DataTable)dataGridMain.DataSource).Rows.Count || i > 0)
((DataTable)dataGridMain.DataSource).Rows.RemoveAt(i);

under certain conditions I get ArgumentOutOfRange exception. I get the
exception if and only if the selected cell in the DataGrid was changed
one or more times before the delete operation. If the selected cell has
not been changed the code above executes smoothly.

I seriously begin to think that this is a bug in the .NET CF. It is
apparent that the variable i cannot be out of range so what is that
exception supposed to mean?
 
T

Tsviatko Yovtchev

Ilya Tumanov [MS] wrote:

First of all, you've assumed number of rows in the DataTable is the same as
number of rows in the DataView/DataTable. You can compare these in a loop to
find our that's not the case even though you're not using filtering and
sorting. Indexes also can't possibly be the same since number of rows is
different.

Yeah, that would be a potential source of problems. It slipped in from
an old version of my code. Thanks for pointing it out.
Next wrong assumption is what row indexes in the DataGrid would not change
while this loop is executed.

That is also not the case as indexes would change as soon as first row is
deleted:



I=1, so far so good. About to delete selected row:



I DataGrid DataView DataTable

0 1 1 1


2 3 3 3 -------- Selected

3 4 4 4



After first delete you've got into total mess (I'm assuming you're
incrementing 'i' at the end of loop):



I=2, row just deleted row @1:



I DataGrid DataView DataTable

0 1 1 1

1 3 3 2 -------- Row is in
deleted state in DT, selected in DG/DV and they are different rows.


4 4



Note you would skip row '3' because it would move to index 1 you've already
processed. Also now you have 4 rows in the DataTable (one in deleted state)
and only 3 of them in the DataView/DataTable. Inevitably you would increment
row index to 3 which would generate an exception.

That's also very true. Rather unfortunately, I just failed to copy/paste
my loop in its eternity. I beg your pardon for this. I am pretty tired
already. The actual code looks like this:

for(int i = 0; i < ((DataTable)dataGridMain.DataSource).DefaultView.Count; )

if(dataGridMain.IsSelected(i))
{ ((DataTable)dataGridMain.DataSource).DefaultView.Delete(i);
}
else
i++;

So that was not the problem either.

As I mentioned in my previous posts the problem occurs if and only if I
select cells from certain columns of the DataGrid before attempting the
delete any rows. If I just select some rows and delete them the code
above runs smoothly.

Actually, I just narrowed down the source of the problem. I get the
exception only if I select a cell in the rightmost column of the
DataGrid before I try to delete some rows. Besides, it happens only if
the rightmost column is of certain size. I noticed that although no
horizontal scroll is displayed the rightmost column is slightly off the
limits of the DataGrid and when I perform a selection in it the grid
gets automatically scrolled slightly to the right.

Here is how it goes in code:

DataGridTextBoxColumn len = new DataGridTextBoxColumn();
len.HeaderText = "Length";
len.MappingName = "Length";
len.Width = (int)(0.1 * this.dataGridMain.Width);
ts_songs.GridColumnStyles.Add(len);


If I change that 0.1 to some other value the problem vanishes. It looks
like I got exactly the size that's problematic :)

So, overall, I think that the ArgumentOutOfRangeException actually has
nothing to do with the indexes of the DataView and the DataTable. It
looks more like something else in the DataGrid goes wrong. Is anybody
aware of such a bug? I am really unwilling to release like this without
knowing what exactly causes the problem.
 
I

Ilya Tumanov [MS]

What's the stack trace from that exception? What is the size of the
rightmost column?

Could you please try running this application on NETCF V2?

(int)(0.1 * this.dataGridMain.Width) - this one can have some rounding
issues.




--
Best regards,

Ilya

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

*** Want to find answers instantly? Here's how... ***

1. Go to
http://groups-beta.google.com/group/microsoft.public.dotnet.framework.compactframework?hl=en
2. Type your question in the text box near "Search this group" button.
3. Hit "Search this group" button.
4. Read answer(s).

Tsviatko Yovtchev said:
Ilya Tumanov [MS] wrote:

First of all, you've assumed number of rows in the DataTable is the same
as number of rows in the DataView/DataTable. You can compare these in a
loop to find our that's not the case even though you're not using
filtering and sorting. Indexes also can't possibly be the same since
number of rows is different.

Yeah, that would be a potential source of problems. It slipped in from an
old version of my code. Thanks for pointing it out.
Next wrong assumption is what row indexes in the DataGrid would not
change while this loop is executed.

That is also not the case as indexes would change as soon as first row is
deleted:



I=1, so far so good. About to delete selected row:



I DataGrid DataView DataTable

0 1 1 1


2 3 3 3 --------
Selected

3 4 4 4



After first delete you've got into total mess (I'm assuming you're
incrementing 'i' at the end of loop):



I=2, row just deleted row @1:



I DataGrid DataView DataTable

0 1 1 1

1 3 3 2 -------- Row is
in deleted state in DT, selected in DG/DV and they are different rows.


4 4



Note you would skip row '3' because it would move to index 1 you've
already processed. Also now you have 4 rows in the DataTable (one in
deleted state) and only 3 of them in the DataView/DataTable. Inevitably
you would increment row index to 3 which would generate an exception.

That's also very true. Rather unfortunately, I just failed to copy/paste
my loop in its eternity. I beg your pardon for this. I am pretty tired
already. The actual code looks like this:

for(int i = 0; i <
((DataTable)dataGridMain.DataSource).DefaultView.Count; )

if(dataGridMain.IsSelected(i))
{ ((DataTable)dataGridMain.DataSource).DefaultView.Delete(i);
}
else
i++;

So that was not the problem either.

As I mentioned in my previous posts the problem occurs if and only if I
select cells from certain columns of the DataGrid before attempting the
delete any rows. If I just select some rows and delete them the code above
runs smoothly.

Actually, I just narrowed down the source of the problem. I get the
exception only if I select a cell in the rightmost column of the DataGrid
before I try to delete some rows. Besides, it happens only if the
rightmost column is of certain size. I noticed that although no horizontal
scroll is displayed the rightmost column is slightly off the limits of the
DataGrid and when I perform a selection in it the grid gets automatically
scrolled slightly to the right.

Here is how it goes in code:

DataGridTextBoxColumn len = new DataGridTextBoxColumn();
len.HeaderText = "Length";
len.MappingName = "Length";
len.Width = (int)(0.1 * this.dataGridMain.Width);
ts_songs.GridColumnStyles.Add(len);


If I change that 0.1 to some other value the problem vanishes. It looks
like I got exactly the size that's problematic :)

So, overall, I think that the ArgumentOutOfRangeException actually has
nothing to do with the indexes of the DataView and the DataTable. It looks
more like something else in the DataGrid goes wrong. Is anybody aware of
such a bug? I am really unwilling to release like this without knowing
what exactly causes the problem.
 

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