Hi,
I have a grid where some of the values in the grid are animating on a timer. I would like to iterate through the visible (ie, visible to the user) rows and refresh the necessary UltraGridCells if the cells are animating.
Is there a way to iterate through the on-screen, visible rows of the grid?
I have tried using the VisibleRowCount, but that returns all of the rows in the grid, and not just the rows being displayed.
I have also tried using the ActiveRowScrollRegion.VisibleRows, but that method occasionally throws an exception.
So far, my best solution is to iterate through all of the rows in the grid, check the UIElement to know if the row is being displayed, and refresh the row as necessary. This does not seem to perform well as the grid could contain 1000s of rows whereas only 50 or so are visible to the user.
Any ideas?Thanks in advance,Steve
Hi Steve,
Well, that's a pretty clear indication that this is a threading issue. You say you are updaing the data source in a thread-safe manner. If you are updating the grid's data source on a thread other than the UI thread, then that's not safe under any circumstances because the data source may fire events that the grid is responding to on another thread. You must always suspend the notifications.
Hi Mike,
The method you provided works well, but I am still seeing the same exception. I did notice one thing, though. We have multiple threads updating the underlying datasource in a thread-safe manner. Each update to the datasource conditionally calls SuspendBindingNotifications depending on the number of updates being done (let's say, more than 10). If I remove that condition, and always suspend the binding notifications, I do not run into any unexpected exceptions with the stacktrace above. When I include the condition to not suspend the binding notifications, I am able to reproduce the error after waiting an undeterministic amount of time. The downside to always suspending the binding notifications is that the overall performance seems slower.
I know this is a rather vague description of the symptoms, but just throwing it out there.
Thanks for your help,
Steve
If you are concerned about getting the best possible efficiency, then you can use the UIElements of the grid directly. Here's some code that uses the UIElements to get the rows in the visible area. This code is assuming that there is only one ScrollRegion in the grid and that thereare no GroupByRows.
private List<UltraGridRow> GetVisibleRows(UltraGrid grid) { List<UltraGridRow> rows = new List<UltraGridRow>(); UIElement element = this.ultraGrid1.DisplayLayout.UIElement; if (element != null) { element = element.GetDescendant(typeof(DataAreaUIElement)); if (element != null) { element = element.GetDescendant(typeof(RowColRegionIntersectionUIElement)); if (element != null) { foreach (UIElement childElement in element.ChildElements) { if (childElement is RowUIElement) { UltraGridRow row = childElement.GetContext() as UltraGridRow; if (row != null) rows.Add(row); } } } } } return rows; }
The timer is a Windwos.Forms.Timer.
In the body of the timer, I try to iterate through the VisibleRows collection of the ActiveRowScrollRegion. Based on the time, we fade the color of the some of the cells in the row. So, each iteration either calls ultraGridRow.Cells["column1"].Refresh() or sets ultraGridRow.Cells["column2"].ForeColor. Is there a better approach to force a repaint of the cells?
Unfortunately, I can't reproduce this reliably. I have to run performance testing tool that creates a large amount of updates to the client application.
I am also running v7.2 of the toolset. Do you think v7.3 would give me better results?
Thanks!
Hm, that's odd. This shows that the exception occurs during a paint, not even during the firing of the timer tick. Is it a System.Timers.Timer or a System.Windows.Forms.Timer?
Can you reproduce this reliably? If so, you should probably Submit an incident to Infragistics Developer Support so they can check it out.