I have created a custom object collection which I have bound to an UltraGrid using an UltraDataSource and implementing the Load On Demand feature. What is the best (or accepted) way to get the grid to refresh when a property on the object changes? Right now the cell data only refreshes if something causes the cell to repaint (i.e., mouse over the cell, sort the column, etc...). If I try to refresh the entire grid each time there is a cell update this slows performance. What I would like to to is only refresh the cell where the data has changed.
If I instead bind the grid to a BindingList and stream updates to the bound properties the grid updates in real-time as I would expect.
Thanks for your help.
What needs to happen here is the UltraDataSource would have to send a notification to the grid to tell it that the row has been updated. It can't do this automatically, of course, in this case, because it doesn't know that the data has changed. So there would have to be a method on the UltraDataSource to allow you to trigger this notification.
Unfortunately, there is currently no such method publicly available. This may be something of an oversight, and I recommend that you Submit an incident to Infragistics Developer Support and report this as a possible bug - although they may consider it a feature request.
One workaround for now would be to invalidate only the cell and not the entire grid. To do this, you would have to get a reference to the grid cell, use it's GetUIElement method to get the element and thus it's Rect, and then you could invalidate just that rect.
Thanks for the answer, this was useful. However I am seeing a problem with memory usage when trying this. I created a grid with 50 columns and 100,000 row and filled it with random data. The I bound it through an ultraDataSource using the Load On Demand model. Then I created an event on my backend datasource, which in this case is just a two dimensional array, which notifies the grid that the datasource has changed. My event handler looks like this:
void dataChanged(int x, int y) { UIElement uiElement = this.ultraGrid1.Rows[x].Cells[y].GetUIElement(); if (uiElement != null) { ultraGrid1.Invalidate(uiElement.Rect); } }
This seems to work, however the problem is that when I begin sending a large number of updates (5000 per second) the memory usage of the application grows with each refresh and never goes down, until the application is using a large amount of system memory. I would guess from your posting on improving performance that the grid doesn't actually create the cell until necessary and this is causing the cell (or the row of cells) to be created? Thanks for your help.
Okay, that makes sense. The memory usage is most likely occurring because you are creating a cell object. By default, the grid does not create every UltraGridCell object, it only creates these as needed. By referencing the indexer of the Cells collection to get a cell, you are causing that cell to be created.
This is discussed in more detail in the WinGrid Performance Guide.
Since you have 100,000 rows it seems reasonable that the cell being updated will not currently be visible on the screen the vast majority of the time. So one thing you might do to make this more efficient is to check row.GetUIElement first. If the row's UIElement is null, you can be sure that the row is not visible on the screen, and thus the cell can't possibly be visible, either, and you can skip the creation of the cell.