Hi,
I have a WinGrid bound to a BindingList containing some objects (class DataObject).
The grid has AllowAddNew set to FixedAddRowOnBotton.
When a click on the AddRow, the BindingLists AddingNew handler is creating a new object, that is displayed in the AddRow. If I now click on one of the other rows, the AddRow is cleared and the new object is removed from the BindingList. This is what I expected.
Now I implement IEditableObject on DataObject, and the grids behaviour changes:
When I click away from the AddRow, the new object is NOT removed from BindingList. Instead CancelEdit() is called (and then EndEdit()), and the object is still displayed in AddRow. There is no longer a * in AddRows RowSelector.
What should I do, to make the grid remove the object from the BindingList, when IEditableObject is implemented?
Regards,
Klaus
Visual Studio 2008.NET Framework 2.0WinGrid ver. 8.2.20082.1000
Hi Klaus,
If CancelEdit is called, then the object should be cancelled and thus removed from the list. If that item still shows up in the grid, then this is either a bug in the grid, or your implementation of IEditableObject is not correctly cancelling and removing the item - or perhaps it's not sending the proper notifications when this occurrs.
If you feel that your IEditableObject implementation is correct and that this is a bug in the grid, I recommend that you create a small sample project demonstrating this and Submit an incident to Infragistics Developer Support.
Hi Mike,
If you bind a grid to a BindingList containing business objects, that don't implement IEditableObject, the grid calls CancelNew(...) on the BindingList.
If the business objects implement IEditableObject, the grid calls CancelEdit() on the object, but forgets to call CancelNew(...) on the list.
The problem is of course, that IEditableObject.CancelEdit() can reset the state of the object, but it doesn't know anything about the collection(s) it is put into. To remove the object from the BindingList, the grid has to call BindingList.CancelNew(..) - that's why it's there.
Developer Support doesn't think it's an error. I'm not happy about it, but I won't pursue it.
My work-around is to wrap my business objects (that implements IEditableObject) in an object, that holds a reference to the business object and a reference to the BindingList. This wrapper class is then able to remove an object from the BindingList, when it is cancelled during creation.
Best regards,Klaus
Resolved this issue by using the AddRowEditNotificationInterface property:
UltraGrid1.DisplayLayout.Override.AddRowEditNotificationInterface = AddRowEditNotificationInterface.ICancelAddNewAndIEditableObject
@Mike: I don't see the attached sample you mention in your response. I'm also encountering this issue and would like to figure out how to resolve it.
@kvill: You mentioned that you have encountered this issue for a long time. Would you be willing to share how you have worked around this? Thanks!
Hi Ken,
You are probably right that the IEditableObject.CancelEdit should not have to know about the List it is in and remove itself from that list. I think it's probably supposed to work the other way around. The List should be hooking into notifications on the object so that is knows when the object is cancelled and removes that item from itself.
But either way, the grid does not get involved in this process. All the grid does is call CancelCurrentEdit on the CurrencyManager. Is it the CurrencyManager/BindingManager that takes it from there. The CurrencyManager is responsible for notifying the list that the item should be removed and it is responsible for sending the proper notifications.
Just to be sure, I tested this against the DataTable. This is the implementation that we use as the standard model for how things should work. I created a small sample project without using our grid, just a TextBox, some buttons, and a Datatable.
I have attached the sample here. If you press the Add button to add a new row to the DataTable, you will see that the TextBox goes blank - it is showing you the new, empty record.
If you press cancel, all the button does here is what the grid does - it calls CancelCurrentEdit on the CurrencyManager. This has the desired effect of removing the newly-added row. So calling CancelCurrentEditor on the BindingManager is all the grid should need to do here. Anything beyond that is up to the BindingManager and the data source itself.
In any case, why use a List<T> as your grid's DataSource? List<T> is an IList, not an IBindingList. So you are going to experience all sorts of limitations in terms of binding functionality. BindingList<T> is designed for data binding and will work a whole lot better, and it also implements IList, so you probably don't even need to change any code to make it work.
I wouldn't be surprised if simply changing your data source from List<T> to BindingList<T> fixes the issue with the TemplateAddRow.
If not, please post a small sample project here demonstrating the issue and we will be happy to take a look at it and tell you exactly why it's not working.
The problem Klaus talks about above still exists. We have been running into this problem for years and we have IEditableObject implemented on our base classes. When these classes are added to a Generic List<T> and bound to a BindingSource it fails to remove items because it only calls CancelEdit() on the individual object and fails to call CancelNew() on the BindingList which would remove remove it from the List<T>. The class inside the list shouldn't have to remove itself from the list.
Also the Objects in the List<T> don't know anything about CancelNew() or CancelAddNew() in Infragistics or in the BindingList. And suggesting an Object should actually call those methods is WRONG and adds a dependency into generic objects that shouldn't exist....This is definitely an IG bug.
-Ken
KlausZachariassen said:If the business objects implement IEditableObject, the grid calls CancelEdit() on the object, but forgets to call CancelNew(...) on the list.
The grid doesn't forget. It intentionally does not call the method becuase it already called the IEditableObject implementation which should already have cancelled the row. The grid assumes that the IEditableObject implementation did what is is supposed to do. It has to make this assumption, because if it cancels the row twice (once through IEditableObject and then a second time for CancelAddNew), then the second call could easily cause an exception, since it will not expect the row to already have been cancelled.
Why not simply have your IEditableObject implementation call CancelAddNew?