I've got a small grid displays data from a many:many list - effectively the user is able to select multiple items from a reference list - but since these lists can be long, instead of showing a listbox with checkmarks, I'm using a grid, populated only with the selections made.
This works fine. A lookup list is used to edit the only column on the grid and it works nicely.
My problem is validation - the user cannot select an item that has already been selected in another row. Doing the actual check in the OnCellDataUpdating() method isn't a problem, and for existing rows, it nicely reverts to the original value. However NEW rows are another matter - the grid creates the new row at the time the user begins editing (and the datasource MUST create a new object in the internal list to match this before editing begins). Thus if validation fails for this new row - we end up with a new (blank) row on the grid, and a new "new row" line beneath it.
Now in an ideal world, I want to keep ALL my business/data logic in my custom DataSource class - so how do i notify the data source that a row should be deleted because the edit just completed was invalid?? If I try to access the parentRow collection directly and remove the row, it does work, but I get a rather ugly message displayed as well.
The alternative is to put code in the grid's AfterRowUpdate() event, and detect a marker left by the datasource for that row, indicating that it failed validation - and the row is selected and DeleteSelectedRows() is called. This works cleanly and gives the end-user-experience I want, but I consider it to be BAD design to be forced to split my validation logic like this. Not the least of which is that when I copy this datasource to several other grids on this form, and other forms, I now have to duplicate this code.
So, does the UltraDataSource have a way of removing rows internally, or is it a hole in the product that needs filling?
When you start editing a new row, the row get added to the data source, but it is not yet comitted. It's in an AddNew state. If you want to cancel the row, all you have to do is call grid.CancelUpdate.
This will also work for an existing row and undo any changes that have been made to the row since the last time the row was comitted to the underlying data source.
You may need to change your UpdateMode on your grid, though to make sure it's set to OnRowUpdate or OnRowUpdateOrLostFocus, rather than updating every time the active cell changes.
That would be nice, if the ultraDataSource class would actually allow me to override the OnRowCancel...etc events in my custom datasource. All the "Cancel" methods on the grid assume that these methods in the datasource are actually working. I've put in a support request notifying them of this bug. I can workaround it by handling the events instead, but it kinda defeats the purpose of having a reusable data class...sigh.
It seems no-one up till now has seriously tried subclassing these for complex operations, as the compile problem is kinda obvious...
Hi,
Well.. I'm not sure what kind of class you are using or what your subclassing is doing. But perhaps it would be easier for you to simply implement IBindingList. Or even derive your data class from BindingList<T> rather than from UltraDataSource. That way you would have a lot more detailed control. Just a thought.