I have a grid that is bound to a DataTable via a DataAdapter.
After applying updates to the table I spin through the table rows checking to see if any of the rows failed to update. If they did then I copy the error message to the Tag of the corresponding grid row so that I can display it when that row becomes active.
This works fine if the data remains in its original order.If the user sorts the data grid however it seems that the indexes of the the grid are no longer the same as the indexes in the underlying datatable.The error messages get assigned to the wrong grid rows.
I though sorting effected only the display - not the index required to reference the grid rows.How do I get the sorted index from the original (as in the underlying table) index?
My code is as follows:
adapter.Update(table)
Dim hasErrors As BooleanFor r As Integer = 0 To table.Rows.Count - 1 If table.Rows(r).RowError = String.Empty Then 'Remove the color that indicates pending changes Grid.Rows(r).Tag = Nothing Grid.Rows(r).Appearance.BackColor = Grid.DisplayLayout.Appearance.BackColor Else 'Add the error message to what we will display for the row hasErrors = True Grid.Rows(r).Tag = table.Rows(r).RowError() End IfNext
Hi,
Sorting the rows in the grid will change the indices of those rows. That is the intended behavior.
It's very hard to get the grid row from the table row, but it's very easy to get the table row from the grid row using the ListObject property. So what I would do is use the InitializeRow event of the grid and use e.Row.ListObject. It will probably return a DataRowView and you can use the Row property on that to get the actual DataRow from your table.
I don't see how the InitializeRow event figures into trapping errors from an Update.
However your explaination of the ListObject property allowed me to change the code as follows:
This seems to work correctly.
Thanks
Hi Mike,
mikedempsey said:I don't see how the InitializeRow event figures into trapping errors from an Update.
InitializeRow will fire any time any cell in the row has been changed. So it's a lot more efficient to use InitializeRow to set the Tag or do whatever you want to do with the row than it is to loop through every tow in the grid every time you make a change.
I don't have anything to check when the contents of a cell changed by the user.(Actually I do already check that the new value can be parsed into the underlying table column data type, but that is a 'local' change)
The loop is for after Update() is called on the data adapter.If the database returns errors I need to assign those messages to the appropriate row.That has nothing to do with changes to the cells contents. (They changed earlier)
Or are you saying that the InitializeRow event fires when the underlying data rows FAIL to commit a change?
I guess maybe I just don't understand what you are trying to do. :)
Hello,
To learn more about the InitializeRow Event, please visit the online documentation found here. Please let us know if you have additional questions regarding the InitializeRow event.
The scenario here is that I am working with a bound grid (through a DataAdapter) that performs batch updates on the underlying database table.
The user may make many changes to many different rows before clicking the Update button.No changes are applied to the underlying table until that time.
Since the data in the grid has already been loaded [and changed] I dont think InitializeRow() will fire after the update completes.
The underlying DataTable contains success/failure indicators for each row that was changed by the user. I need to remove a background color I applied for each successfully updated row or transfer the error message to the row's Tag property if the update failed for that row.
The looping method does work, but if InitializeRow() does fire at this time [with some way for me to know that it is firing as the result of an update] then I could use that as an alternative.
From my understanding the InitializeRow event should only fire once for each row. To test this, I added a breakpoint to the event and updated a cell. After the cell updates, the InitializeRow event fires once and ReInitialize returns true. If possible, can you attach a sample that shows the event firing more than once? This will allow me to debug your solution to better assist you.
I tried using the Initialize() event in which I set a switch immediately before calling the DataTable.Update() method and reset it immediately after.
Then I only handle the Initialize event if the switch is set.
This partially works. The problem is that the event fires TWICE for each row updated. I assume it must be Before/After since the first time it fires the RowError property is always empty, but the second time it is populated if there was an error.Other than remembering the Row.Index and ignoring the event if it was different from last time (ie ignore the 'before') I dont see any property to tell me whether this is a before or after event.(I don't understand why it would make sense to fire twice anyway)
Am I missing a property that differentiates between the 2 (It's not 'ReInitialize' - that is true both times)
The ReInitialize Property may be what you are looking for here. It will fire every time a row that has already been initialized gets reinitialized (or as the result of an update in your grid). To learn more about this property, I recommend looking at our online Docs found here.
Please let me know if you have additional questions.