Hi,
I'm having some issues with the performance of the ultrawingrid. In my situation, I have a grid with a group by column and about 8000 rows. I need to loop through the individual rows to set values to some unbound columns. However, rather than the assigning of those values, just the looping through the rows (actually: getting the enumerator) causes a delay of a few seconds.
I created a small sample project demonstrating the problem. The project groups a column in the grid and fills it's datasource with 10000 rows. When clicking the test button, it refills the datasource, and loops through the rows. This takes a few seconds, and is too long for a smooth user experience.
My question is, how can I speed up the enumeration of the rows?
I already tried the SuspendUpdate and SuspendRowSynchronization as mentioned in the performance guide, but that didn't help. I also tried the GetRowEnumerator method, but that didn't help either. I hope you can. Thanks in advance.
I'm using version 10.3.20103.1000
Hello TorX,
I`m not sure what is your final goal, but do you think that it is possible to use ultraGrid1_InitializeRow() event, instead of Loop to set the values in your UnboundColumn ? Or maybe you could use UltraCalcManager to set the values in your UnboundColumn ? Of course you could try miltiple thread / backgroundworker to prevent hang up of your application.
Let me know if you have any questions.
Thanks for your reply. I've just tried the InitializeRow approach, but I still have the same delay in the UI (however I can't measure it anymore using a StopWatch). I don't think a background worker can help, because I still have to assign the values in the UI thread, which would freeze up the UI. Is there another way?
By the way, without grouping there is no delay. But unfortunately, our users need the grouping (because of the many rows).
I agree with you that using a background worker thread would not help, and could easily cause more problems.
I'm a little puzzled, though - when you use InitializeRow, when exactly is the delay? What exactly is delayed? The display of the form?
My guess is that your InitializeRow code is probably not as efficient as it could be, because setting the value of a cell in InitializeRow is very fast and should not cause any delay at all.
Can you post your code in InitializeRow?
Thank you for sorting this out.
I just wanted to let you know that we looked into this more thoroughly and it's pretty much as I thought.
When something changes, there are basically two code paths the grid can go down when rebuilding the data.
One approach is for the grid to blow away everything - all the GroupByRows and DataRows and then rebuild everything from scratch. This is what would happen if you changed the Grouping - like if you added or removed a GroupByColumn.
The other approach is to try to keep as much as possible and only update the rows that were changed. This second approach is usually much more efficient and it also has the advantage of being able to maintain the state information on the rows. So if you added a single row to the data source, the grid would just add in that one row and put it under the property GroupByRow. And if some other row were selected and the grid was scrolled to a particular point, everything would stay as it was.
The second approach would even be faster, if you were removing 10 rows, or 100 rows. The performance issue here steps from the fact that you are removing and re-adding ALL of the rows, and there are 10,000 of them. So the grid is trying to rebuild them one at a time, because it doesn't know enough to blow away everything.
We considered changing this in the grid, but it's tricky. The grid could detect that none of the original 10,000 rows are still in use and blow away everything.
But we decided against it for 2 reasons:
1) This would cause a change in behavior. It's the same change in behavior that my workaround causes - you will lose the state information - mainly the scroll position. This probably isn't a big deal, and may even be desirable, but we don't want to change it and potentially break existing applications if we don't have to.
2) This solution would only work if you removed all of the rows. If you removed 9,999 rows, it wouldn't make any difference.
Overall, I really think that if you are replacing all of the rows, you are better off just attaching a new DataSource to the grid, rather the re-using the existing one.
I did, however, find another workaround which requires a little less code. Forcing the grid to refresh the rows after you remove all of the items form the data source, but before you've added the new ones works just as well. And you can do that simply by accessing the row count.
private void FillItems() { Items.Clear();
// Force a refresh int x = this.ultraGrid1.Rows.Count;
for (var i = 0; i < 10000; i++) Items.Add(new Foo(i.ToString(), GetGroup(i))); }
Ok, thank you for the clarification.
TorX said:What do you think is the best way to handle this situation?
It's really a coin toss. If the workaround I gave you here is working, I'd stick with it, I guess. No reason to change your code any more than you have to.
Setting the DataSource might be more efficient, in theory, since it avoids sending 1001 notifications to the grid. On the other hand, those 1001 notifications are not causing an immediate performance problem - the grid is handling them very efficiently. Setting the data source is also more destructive. You will lose the Selected and Active rows and the grid's current scroll position, for example. In this case, those don't matter, since you are removing all of the rows, anyway. But if you were only removing a few rows or modifying rows instead of clearing everything, it might make a difference.
Infragistics Mike Saltzman said:If you are still seeing the same issue in my updated sample, then it could be because I am using the latest service release of NetAdvantage 10.3 and you are using an older version.