The purpose of this article is to provide some general programming practice guidelines and troubleshooting tips to improve performance when using the UltraWinGrid control. Not all of the tips provided here will apply to every application, but it should help with the most common performance issues a developer is likely to encounter.
If you are concerned about reducing the amount of memory used by the grid, then there are several important things you can do to reduce it.
The grid does not create UltraGridCell objects for every row of data. Cells are only created as neccessary. So whenever possible, you should avoid accessed a cell. For example, suppose your code is using the InitializeRow event of the grid in order to calculate a total. For example:
}
This code references three cells in each row of the grid, thus creating a lot of objects which are potentially unneccessary. This can be avoided using methods on the row to deal with cell values, rather than the cell objects themselves. Like so:
By using the GetCellValue method, we can eliminate 2 cells per row in this example and save memory.
Another common use for the InitializeRow event is to apply an appearance to a cell based on the Value of that cell. Applying an appearance to a cell requires getting a reference to the UltraGridCell, so that is unavoidable. But you can save memory by re-using the same appearance object for multiple cells. Suppose, for example, that you want to change the ForeColor of a cell to red for negative numbers and black for positive numbers. You might do something like this:
This code will create a cell for every row. That is unavoidable, since the cell must be created in order to have an Appearance. The bigger problem here is that the Appearance property on the cell is lazily created. That means that we are not only creating a cell for each row, but a new Appearance object for each row. And since there are only two possible colors, we end up creating a large number of identical appearance objects.
A better way to do this is to create the Appearances we need up front and then re-use the same appearance wherever it is needed.
Another benefit to this approach is that you can change the appearance everywhere en masse. For example, suppose your users want to use Green instead of Black for positive appearances. You could, at run-time, set the ForeColor of the “Positive” Appearance object, and every cell in the grid that was using that appearance would update automatically.
In the interest of keeping the information here helpful, on-topic, and easier to follow, I'm locking this thread. If we find the need to edit the information here, or to add to it, we'll unlock the thread to make these changes.
For anyone who has additional questions, comments, or discussions regarding the WinGrid Performance Guide, please feel free to create a new thread, and use a hyperlink to refer back to this one.
Thank you, everyone!
Mike Saltzman"]The problem is, what happens if you specify that the grid should use the existing layout and the layout doesn't actually match exactly
Mike Saltzman"]I think you might not be using the right terminology here. It sounds to me like you have 5 bands, not 14
Mike Saltzman"] How long is the delay, exactly?
How long is the delay, exactly?
Mike Saltzman"] What kind of data source are you using for the grid?
What kind of data source are you using for the grid?
I'm not sure how you would use the UltraDataSource as an intermediary. What I ended up doing was basically abandoning the designer (it seemed to have lots of problems after the second level anyway) and wrote code to create the five levels of bands myself in the control constructor. This resolved the delay. Apparently creating all the bands I wasn't using was what was causing the delay.
jbailey@baileysw.com said:Then why bother looping through the data source and adding code for the structure if its just going to be ignored at run time?
Because it's not "ignored" at run-time. When the grid's DataSource is set at run-time, the grid needs to examine the data structure it is being bound to to determine if the current layout in the grid matches up. If it does, then the grid uses the existing layout. If not, then the grid throws away the layout in favor of the new data structure.
jbailey@baileysw.com said:Also, since I do know that the structure will be the same, shouldn't it be possible to turn this functionality off and tell the grid to assume the structure matches?
I suppose that might be possible. You should Submit a feature request to Infragistics.
The problem is, what happens if you specify that the grid should use the existing layout and the layout doesn't actually match exactly? The grid would probably have to raise an exception at that point.
jbailey@baileysw.com said:Again, this represents a project plan task list. The tasks has a collection of parent tasks, predecessor tasks, and user resources assigned (which each have their collection of tasks). The grid steps through each one up to five levels deep creating more than 140 bands. Only the task collections would be populated and viewed through the grid, the rest are set to not be visible (although they would be populated and used elsewhere).
I think you might not be using the right terminology here. It sounds to me like you have 5 bands, not 140. A band is like a table or a relation. Each island of Data is not a band.
If you have 5 bands and your application is experiencing serious performance problems, then something else is probably wrong. Perhaps there is some other area of the code that is inefficient or you are running on a particulatly slow machine. Or perhaps you data source is not an efficient one.
As a test, what happens if you use an UltraDataSource component and set up the same basic structure and bind that to the grid? Does the same delay occur? If so, then it's probably just the normal processing of the DotNet BindingManager. If not, then it indicates some inefficiency in the DataSource, itself. In which case, you might want to consider using an UltraDataSource in on-demand mode as a sort've intermediary between the grid and the data source.
Mike Saltzman"]When you assign the DataSource to the grid, it doesn't neccessarily know that it's the same one you assigned at Design-time. In fact, it's not the same instance, so it has to get the structure again.
Mike Saltzman"]But I have never seen this cause any significant performance issue when MaxBandDepth is set to a reasonable number, and 5 is certainly reasonable.
Mike Saltzman"]It's hard to guess without knowing more about your application. But I can tell you that the grid will not load child rows by default, so only the root-level rows of the grid should be created initially
ADASDev said:I was refereeing to the 40 rows in the grid, I will look into Filtered UltraDropDown. and the original article some useful hints.
So how many items are on the ValueList?
It occurs to me that if you are changing the ValueList on the cell, then the Value in that cell is unlikely to be valid for the new list. So perhaps what you should do is set the Value of the cell to null or DBNull.Value before you change the ValueList.
I'm not entirely sure that will help, but it's worth a shot. :)