Gridview deletion problem

F

Flomo Togba Kwele

I created a form, a datasource (Product table from AdventureWorks)
from the Data Sources tab, and dragged the Product table from the Data
Source tab to the form's designer surface.

This created a dataset, bindingsource, tableadapter and
bindingnavigator.

I placed the following code in the click event of the delete button on
the bindingnavigator:

Me.Validate()
Me.ProductBindingSource.EndEdit()
Me.ProductTableAdapter.Update(Me.AdventureWorksDataSet.Product)

When running the app, I select a row and click the delete button on
the navigator. It disappears. However, when I exit the app and
re-enter, the row is still there.

As another test, if I select the row again, and click the delete
button, and click it once more, the row is actually deleted from the
database.

In debug I place a stop after the Validate method above. The
underlying dataset shows false for HasChanges after the first click of
the delete button and the selected row shows Unchanged for its
RowState.

However, after the 2nd click of the delete button, the dataset shows
true for HasChanges and Deleted for the RowState associated with the
row.

What is wrong with my code?

Thanks
 
W

WenYuan Wang

Hi Flomo,
Based on your description, I understand that you encountered an issue when
adding code in the delete event of the BindingNavigator. If I misunderstand
anything here, please don't hesitate to correct me.

According to my test, I find this issue only appears in VB.net Project. I
have reproduced this issue on my machine in both C# project and VB project.
In C# project, if I click the delete button, the row state will be changed
to "Delete", but this state will not be changed in VB project.

I think I need to perform more research and discuss with other engineers on
this issue. I will reply to you as soon as possible.

Thanks for you understanding!
Have a good weekend.
Wen Yuan
===============================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
===============================
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
W

WenYuan Wang

Hi Flomo,
Thanks for your wait.

I have debugged this issue and discussed with other engineer in our team.
We find the root cause of this issue is the difference of the behavior
between winform project in C# and VB.net. In C#, delete() method will be
called before the delete event fired. For this reason, we can find the row
state has been changed to "delete". But in VB.net, this method is called
after the delete event fired. For this reason, you noticed that the row
would be deleted if you click the "delete" button twice.
Base on my test, we can walk around this issue by calling
Me.bindingSource.RemoveCurrent().

For example:
Add the "BindingSource.RemoveCurrent()" method before your code in the
click event of the delete button on the bindingnavigator:

Me.ProductBindingSource.RemoveCurrent ()
Me.Validate()
Me.ProductBindingSource.EndEdit()
Me.ProductTableAdapter.Update(Me.AdventureWorksDataSet.Product)

Please try the above and let me know whether or not this is what you want.
I'm glad to work with you.
Have a great weekend!
Wen Yuan
 
F

Flomo Togba Kwele

Thanks for the reply, Wen Yuan.

In order to test your suggestion, I changed the table to DatabaseLog,
because I didn't have to worry about referential integrity inteferring
with deletion.

I launched the form and clicked on the DatabaseLogID column so that
the IDs were in sequence and I could see the results of the deletion
more easily.

I selected the row with the DatabaseLogID of 6 and pressed the Delete
button on the BindingNavigator. Before I deleted, the sequence was
from 1 to 10 with no missing IDs visible in the GridView. After I
deleted, it went from 1-5 and the 8-10 - 6 and 7 had been visually
deleted!

I exited the form and re-entered. The row with the ID of 7 was there,
so the code you gave me caused two rows to be visually deleted but
only the selected row to be logically deleted.

Can you replicate this behavior? If you can, what can I do to work
around this problem?

Thanks, Flomo
 
W

WenYuan Wang

Hi Flomo,
Thanks for your reply.

I have reproduced this issue. I think this is because RemoveCurrent()
method must have been called after the click event automatically.
The item (id six) is deleted because we call BindingSource.removecurrent()
manually in DeleteItem_Click evemt, and tableadatper.Update(Table) will
delete this item (id six) from database. But after the click event fired,
bindingNavigator will call BindingSource.removecurrent() again by design.
For this reason, the item (id seven) will also be deleted.

I'm sorry the workaround in my frist reply doesn't work. I think the way to
approach this, we should remove the Delete button and add a new button into
navigator. We can type our code into Item_Click event and this button will
not call the RemoveCurrent() automatically.

Could you please try the above and let me know whether or not this is what
you need. If you have any further questions or concerns on this, please
feel free to let me know.

Best regards,
Wen Yuan
 
F

Flomo Togba Kwele

Thanks, Wen Yuan, it worked as you stated. I created a new button on
the BindingNavigator and copied the code you originally posted into
its click event. It delete visually and logically a single row, as
expected.

I don't understand/see what the original delete button on the
BindingNavigator was doing. Why is it calling its removecurrent method
silently?
 
W

WenYuan Wang

Hi Flomo,
Thanks for your reply.

I have reproduced the issue and debugged on it.
In general, if we want to delete a row from DataGridView. We click the row
in DataGridView and click the Delete button on the BindingNavigator. The
item we selected from DataGridView will be visually deleted. After we click
the Save button on the BindingNavigator, this row will be logically deleted.

In order to delete the current row from DataGridView, Delete button will
fire the OnDelete event of BindingSource. Then BindingSource will call
removeCurrent() method to remove the current item from the BindingSource.
That is the behavior of Delete button.

The root cause of this issue is that the Delete button fires the OnDelete
event of BindingSource after the BindingNavigatorDeleteItem_Click event.
For this reason, the removeCurrent() method will be called twice in my
first workaround. We should remove the original Delete button, add a new
button and type our code into its click event.

If there is anything unclear, please feel free to reply me and we will
follow up. I'm glad to work with you.
Hi Flomo,
Thanks for your reply.

I have reproduced the issue and debugged on it.
In general, if we want to delete a row from DataGridView. We click the row
in DataGridView and click the Delete button on the BindingNavigator. The
item we selected from DataGridView will be visually deleted. After we click
the Save button on the BindingNavigator, this row will be logically deleted.

In order to delete the current row from DataGridView, Delete button will
fire the OnDelete event of BindingSource. Then BindingSource will call
removeCurrent() method to remove the current item from the BindingSource.
That is the behavior of Delete button.

The root cause of this issue is that the Delete button fires the OnDelete
event of BindingSource after the BindingNavigatorDeleteItem_Click event.
For this reason, the removeCurrent() method will be called twice in my
first workaround. We should remove the original Delete button, add a new
button and type our code into its click event.

If there is anything unclear, please feel free to reply me and we will
follow up. I'm glad to work with you.
Best Regards,
Wen Yuan
Microsoft Online Community Support
===============================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
===============================
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
F

Flomo Togba Kwele

Wen Yuan,

In working with the code further, I need some advice on an appropriate
approach.

Given that the following code works:

Me.ProductBindingSource.RemoveCurrent ()
Me.Validate()
Me.ProductBindingSource.EndEdit()
Me.ProductTableAdapter.Update(Me.AdventureWorksDataSet.Product)

I can get an error from the update method on a referential constraint
- the row is used somewhere else and cannot be deleted.

I can wrap the update in a try-catch block so that I retain control
over the process, but the item has already been removed from the grid
in the first statement, the RemoveCurrent method. The user sees the
error message (I use an error provider in the try-catch block) that
it can't be deleted, but the item is visually deleted.

What approach can I use to avoid this?

Thanks, Flomo
 
W

WenYuan Wang

Hi Flomo,
Thanks for you reply.

Each bindingSource is related to a datatable/dataset. After
bindingsource.removecurrent() method has been called, the row in the
datatable will be flagged as "deleted". If we want to cancel this transact,
we can call rejectChanges() method.

For example; CType([Me.BindingSource.DataSource],
System.Data.DataSet).RejectChanges()

Could you add this statement into try-catch block to check whether or not
this method works for you.
I'm very glad to work with you. Please reply if you have any further
problem or concerns on this.

Hope this helps.
Have a great day!
Wen Yuan
 
R

RobinS

You probably wouldn't be binding one custom object, you would be using a
list. That's a whole different ball of wax. I did this, and had my list
inherit BindingList(Of company) for my company objects. Then I
implemented a whole bunch of methods, overrode the InsertItem and
RemoveItem methods of the list, etc., etc.,etc.

It's quite a bit of work, and took me information from 2 books to figure
out, the primary one being Brian Noyes' Data Binding book.

Robin S.

Flomo Togba Kwele said:
And if it's not a dataset but a custom object?

Hi Flomo,
Thanks for you reply.

Each bindingSource is related to a datatable/dataset. After
bindingsource.removecurrent() method has been called, the row in the
datatable will be flagged as "deleted". If we want to cancel this
transact,
we can call rejectChanges() method.

For example; CType([Me.BindingSource.DataSource],
System.Data.DataSet).RejectChanges()

Could you add this statement into try-catch block to check whether or
not
this method works for you.
I'm very glad to work with you. Please reply if you have any further
problem or concerns on this.

Hope this helps.
Have a great day!
Wen Yuan
 
W

WenYuan Wang

Hi Flomo,
Thanks for Robin's reply.

As Robin said, if your bindingsource binding a custom object or list,
rather than an dataset, we should have to implement a bunch of methods,
such as InsertItem(), RemoveItem() and also RejectChanges() method.

Please feel free to let me know if you have any further questions or
concerns on this.
I'm glad to work with you.
Wen Yuan
 
W

WenYuan Wang

Hi Flomo,

I Just want to check if the issue has been resolved? If it still persists,
please don't hesitate to update here.
We'll go on to assist you on it. Thanks.

Best Regards,
Wen Yuan
 

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