I found that UltraGrid is very slow to refresh after i make changes to the attached UltraDataSource. I followed Mike's article about UltraGrid's performance and added
this.ultraGrid1.BeginUpdate();this.ultraGrid1.SuspendRowSynchronization();
and corresponding Resume and EndUpdate functions but that didn't improve matters much. After some experimenting I got reasonable performance if I just set DataSource of my grid to NULL, do changes to data source and then assign my data source back to grid.
I just think I'm missing something here.
What kind of changes are you making?
Any time you make a change to the data source, like adding, deleting, or editing rows, the data source notifies the grid of the change and the grid responds. So if you make a lot of changes all at once, it can be a performance issue.
BeginUpdate tells the grid not to paint, so that will help improve performance.
SuspendRowSynchronization tells the grid not to synchronize the rows, so that will help some more.
But there is still some processing going on in the grid. So if those methods don't help, then we'd have to know exactly exactly what you are doing to the data source and consequently what notifications the grid is getting so we could see why the grid is slow.
If you can duplicate the problem in a small sample project, we could check it out and maybe improve the performance or give you tips on how you can make it faster.
Thanks Mike for the prompt response.
Here is very simple sample code I put together that illustrates the problem. Without resetting DataSource it runs for ~8 seconds. When you first set DataSource to null, do your changes and set it back to ultraDataSource it takes less than a second.
//ultraGrid1.DataSource = null;this.ultraGrid1.BeginUpdate();this.ultraGrid1.SuspendRowSynchronization();try{ UltraDataRow row = ultraDataSource1.Rows.Add(new object[] { "Data1", "Data2", "Data3", "Data4", "Data5" }); for (int i = 0; i < 30; i++) { UltraDataBand band = ultraDataSource1.Band.ChildBands.Add(i.ToString()); //don't know if there is an easier way to inherit parent band's columns foreach (UltraDataColumn column in ultraDataSource1.Band.Columns) band.Columns.Add(column.Key, column.DataType); UltraDataRow row2 = row.GetChildRows(band).Add(new object[] { "BandA", "Data2", "Data3", "Data4", "Data5" }); } //ultraGrid1.DataSource = ultraDataSource1;}finally{ this.ultraGrid1.ResumeRowSynchronization(); this.ultraGrid1.EndUpdate();}
This code is very strange. I ran it, and it is indeed very slow. But I think the problem is that you are creating a child band for every parent row. Why are you doing that? Is there some reason you need to create an entirely different band for each row in the parent band?
I was just trying to reduce my actual code to a small sample that reproduces the problem. In my real code I have an hierarchical structure with a lot of nested levels and a lot more rows so the problem is even more acute.
I managed to get decent performance by detaching and then attaching back my datasource and Saving and loading back my DisplayLayout so that I still have column formatting, etc. One weird thing is that saving/loading back of DisplayLayout does not preserve Visible Header index - after DisplayLayout.Load my columns are in the wrong order.
Lev said:I was just trying to reduce my actual code to a small sample that reproduces the problem. In my real code I have an hierarchical structure with a lot of nested levels and a lot more rows so the problem is even more acute.
Well, the sample you have here is not really representative of the real issue, then, so it's not really much good to us in terms of figuring out what's going on here.
Are you doing something similar in your real application - and by that I mean, are you adding a large number of bands like your sample is doing? If so, then that might explain what's happening here. If you have a very large, complex, hierarchy of data with a lots of levels, then the BindingManager in DotNet is going to have serious performance issues. These issues would not occur when the data is not bound to the grid, because without the grid, the BindingManagers would not be created up front.
The sample I provided is very much representative of the issue - that was the whole point of creating the sample. Sounds like it's a problem inherent in the design of ultragrid. UltraDataSource by itself has no problems with large number of bands, and BTW 30 is NOT a large number of bands, ultragrid by itself has no problem with that number of bands - it's the combination that is not working well together.
So would you suggest I do what I do right now - unbind ultragrid, do changes to datasrouce and bind it back? Or is there a better solution?
30 is quite a large number of bands in my opinion. In my experience, the sheer number of BindingManagers will cause serious performance problems in Visual Studio, regardless of what kind of data source you are using, when you reach about 8 bands.
Of course, there is no problem with UltraDataSource by itself, because when you just have the UltraDataSource and it's not bound to anything, no BindingManagers are created. The BindingManagers are created by the grid when you bind it.
Are you saying that there is some other data source in which you can add 30 bands while it's bound to the grid and it's not a problem? If so, what data source are you referring to?
Lev said:So would you suggest I do what I do right now - unbind ultragrid, do changes to datasrouce and bind it back? Or is there a better solution?
That seems like a reasonable way around the issue. It probably works better because the grid doesn't have to respond to each individual notification from every BindingManager every time you add a band - it only has to create everything once.
Hello,
I believe that you have come to resolution in the mentioned thread by you: http://community.infragistics.com/forums/t/57190.aspx.
Please do not hesitate to contact us if you need any additional assistance.
Lev, I have a similar problem now where adding columns to bands to my children causes a significant increase in load up time for the grid.
My situation does not allow me to set the datasource of the grid to null, update the UltraDataSource and then rebind it. Did you figure out a different solution to this problem?
I posted more details of my situation with a total of three problems on the following thread
http://community.infragistics.com/forums/t/57190.aspx
If anyone from the Infragistics team needs a simple little project that reproduces any of the problems highlighted let me know as i have one waiting.
So far i have had to put the main updating call on the GUI thread to stop the grid kiling my app and just taking the hit of the speed degradation.
Thanks Mike,
8 Bands is a large number when you pull data from joined tables in database - I agree with you on that one, i haven't seen many queries that join more than 8 tables.
When you populate your own UltraDataSource with adhoc data or your data has a recursive relationship you can very easily have very large number of bands. In my application I have a recursive parent/child relationship with many levels of nesting, and each parent level requires creation of a new band.
I guess I'll stick with unbind, populate and bind again approach for now.