Your Privacy Matters: We use our own and third-party cookies to improve your experience on our website. By continuing to use the website we understand that you accept their use. Cookie Policy
145
How to reduce memory usage when setting Cell Appearance?
posted

Hi,

I need to set the appearance (backcolour, forecolour, fontdata.name) of a large number of cells in a grid (over 100,000), and wonder which approach is recommended to a) reduce memory usage and b) achieve reasonable performance.

Initially, I was using code like the following:

cell.Appearance.ForeColor = colorBilledAndPaid; 

and I noticed that the heap contained 130 thousand Infragistics.Win.Appearance objects (as reported by windbg) -- approximately 1 per cell whose Appearance was being changed.  I noticed another post on this forum suggesting that, to improve performance,  cell Appearances should be set using predefined Appearance objects, so I changed to using code like the following:

// during form startup:

            paidCellAppearance = (Infragistics.Win.Appearance)cellAppearance.Clone();
            paidCellAppearance.ForeColor = colorPaid;
            paidCellAppearance.FontData.Bold = DefaultableBoolean.True;

// later, when painting the cells:

            cell.Appearance = paidCellAppearance;

Unfortunately, this approach used even more memory, and when I checked the heap using windbg there were now over 100,000 UltraGridCell objects (but the Infragistics.Win.Appearance had been reduced to a few dozen, as expected).

Is it normal that setting the Appearance of a cell would cause a new object to be created in memory (one per cell)?  If so, is there a different approach that is recommended when setting these colour and font properties for a large number of cells?  

If the per-cell memory usage isn't normal, then do you have any suggestions on what I might be doing to cause these UltraGridCell objects to be created on the heap?  The code that I'm using to access the cells involves hundreds of lines across 10 methods so I won't paste it all here, but the important parts are:

                foreach (UltraGridRow row in gridBuyLines.Rows.GetAllNonGroupByRows())
                {

                    // paint the child band
                   UltraGridRow airing = row.GetChild(ChildRow.First);
                   while (airing != null)
                   {
                      paintRow(airing);
                      airing = airing.GetSibling(SiblingRow.Next);
                   }
                   // paint the parent row
                   paintRow(row);
               }

... 

 private void paintRow(UltraGridRow row)
 {

                for (int intWeekNumber = 0; intWeekNumber < IntNumWeeks; intWeekNumber++)
                {
                    string strColumnName = "IntAiringsWeek" + (intWeekNumber + 1);
                    row.Cells[strColumnName].Appearance =  paidCellAppearance;
                    // actually,various if statements are used to determine which Appearance object to use here -- it isn't always paidCellAppearance, and not every cell has its Appearance set, but over 100,000 cells do
                 }

Sorry if this problem description is somewhat lame.  If the 2nd approach that I used is the right one but I need to set the .Appearance property more sparingly, then I'm OK with that.  (Until now, I hadn't realized that setting Appearance at the cell level was going to be a performance problem). But I just wanted to make sure that I wasn't barking up the wrong tree before restructuring the code.

Thanks,


Dan.

Parents
No Data
Reply
  • 469350
    Verified Answer
    Offline posted

    Hi Dan,

        There's nothing lame about your description at all, it's all very clear.

        Everything you describe here is perfectly normal and correct.

        If you set a property on an Appearance, then the grid lazily creates an appearance object. So if you are going to be applying the same set of colors and settings to a lot of different cells, the best thing to do is use InitializeLayout event and use e.Layout.Appearance and create all the appearances you need up front. Then you assign them to the cells inside the InitializeRow event. 

        The only thing I am a little fuzzy on is why this approach would use MORE memory than the approach of setting an appearance on each cell. I think you must be mistaken there. Whether you set the cell.Appearance.BackColor to a color or set the cell.Appearance to an Appearance object, the grid has to create a cell object in memory. So both approaches would be creating 100,000+ cells, but only the first approach would create 100,000+ appearance objects.

        One thing you might try is to use the InitializeRow event instead of looping through all of the cell in the grid. This probably won't make much difference in you only have a single band in your grid because the grid will iniitalize all of the root-level rows anyway by default (although there may be a way around this - see the next paragraph). But if your grid is a hierarchy, then this will spare you from creating cells in the child rows until they are expanded.

        Also, it might help you to set the e.Layout.LoadStyle to LoadOnDemand. This will tell the grid to only load rows as needed for display. So this will help with the root-level rows. But this will not help if you sort or filter the grid because that will force all rows to be loaded. 

        Another thing to watch out for is your 'if' statements that are examining the cell value. You are probably doing something like this:

    if (e.Row.Cells["My Cell"].Value == x)

        This code refers to a cell, though. So you will be creating the cell object even if you don't apply an appearance to this cell. A better way to do it is like so:

    if (e.Row.GetCellValue(e.Row.Band.Columns["My Cell"]) == x)

        This gets the value of the cell without creating the cell object. 

        Finally, if none of this helps you enough, you can probably use a DrawFilter instead of using Appearances. Using the DrawFilter, you can basically intercept the drawing of the cell and change the colors right before it paints. The tricky part of this is determining which elements draw which part of the cell. If you want to try this approach, I recommend checking the Infragistics KnowledgeBase for articles and samples of DrawFilters. Also, get the Infragistics UIElementViewer Utility. It will be a huge help in identifying UIElements.  

         

         

     

     

Children