I'm having a strange problem with objects deleted through the UltraGrid/BindingSource. I'm using the entity framework. The objects are involved in a relationship (something like Orders -> OrderItems). The grid is displaying the OrderItems collection; I press the delete key and the row (OrderItem) dissapears. However, when I call EF's SaveChanges() it raises a condition which says that the relationship is deleted but the object still exists and must be deleted in my code.
From other posts in this section I've read that the grid asks the binding source to delete the objects. But, the only methods I see on the BindingSource are: Remove, RemoveAt and RemoveCurrent. So, it seems that no one is actually deleting the object?
Of course I think the EF should do this *and* it does (sort of): When an OrderItem is actually deleted, it removes that object from the collection of OrderItems. But, if you remove the item from the collection it acts as if there's a problem in your business logic. In Other words, it says "You can't have an OrderItem hanging around without an Order. You must delete the object).
The bottom line here is that I need to delete the object. Although the BindingSource has a ListChanged event (ItemDeleted), the object is not available at that time.
I've got two solutions that work:
1. In the grid's BeforeRowsDeleted event, I build a list of objects that need to be deleted. Then, in the grid's AfterRowsDeleted, I delete the objects. This appears to work. I can call SaveChanges() without any errors.
2. In the grid's BeforeRowsDeleted event I delete the objects from the data context and set e.Cancel = true. I can call SaveChanges() without any errors. However, I would have to prompt the user before deletion because the grid's not gonna do it if I cancel.
I'm wondering if solution 1 or 2 is better in terms of hidden consequences that may show up later? I really don't like either of these solutions. Is there a better way to get these objects deleted (not just removed)?
Thanks,
Vincent
Hi,
The grid doesn't deal with the BindingSource object directly, it deals with the BindingManager and the IBindingList interface. To be specific, the grid calls the IBindingList.RemoveAt method.
That's the only way the grid (or any bound control) can delete a row. It's up to the data source to know that the row is being deleted. If you do this on a DataTable, the DataTable doesn't actually delete the DataRow, it just marks it for deletion. It needs to keep the DataRow object around, or at least some record of it, so that it knows what to do when you try to update the back end. In other words, it stores the information from the deleted row, so that it can update the database and delete the corresponding row later on.
So ultimately, it's the responsibility of the data source to handle what happens to removed rows, the grid has no control over this.
Both of the solutions you list here seem like they are perfectly valid to me. I'd probably go with solution #1, myself. It just seems a little bit cleaner and more intuitive. And you can utilize the grid's built-in confirmation dialog.