views:

173

answers:

3

I am using a DataGridView control in my app at the moment and I am hitting a weird memory issue with it. I am not using DataBinding at all, just manual population. The data that I am putting in there is not a lot at all. We're talking about 20 rows by 20 columns of data at the most usually.

The work flow for that control is that I have a ComboBox with different "data sets" that I load as you pick them. So a common usage scenario is cycling through the data sets in the comboBox and seeing them render in the dataGrid. What I am seeing is that when people cycle through the data sets, the app memory usage jumps from 100MB to 1100MB instantly and then drops back down when GC kicks in. But if you cycle through the data sets quickly (i.e. faster than the GC kicks in), you will run out of memory and the app will die.

After debugging, I found that the MAIN reason the memory jumps up like crazy is that I have some columns in that datagrid that are of Image Type. I use them to display a 16x16 icon that indicates status for that row. These icons are stored in an ImageList and I just set them as the value for that cell as I populate the rows of the data grid. If I take out the images and replace them with simple text, I see absolutely no memory spikes whatsoever.

So what is the deal here? Why do images, tiny 16x16, cause the control to go crazy on my with memory like that?

More info:

My logic as you switch data sets is:

  • Clear all the grid rows: dataGrid.Rows.Clear();
  • Clear all the columns: dataGrid.Columns.Clear();
  • Add the columns to the dataGrid control: (most type string, and some DataGridViewImageColumn)
  • Add the data I have row by row using dataGrid.Rows.Add(object[] data); (the data includes the images I need to use as icons).
A: 

In your 3rd paragraph you say you have your icons in an ImageList, but in your bulleted list of logical steps you say you are adding the images you need as icons as an array of objects. Could the ImageList added to the dataGrid be at fault?

aastle
The DataGrid has an Add method that takes an entire row in the form of an object array. So for the columns in that row, I add the icon I want by specifying it out my imagelist like this: ImageList.Images[x]. So it's all coming out of that imageList. I tried to see if there was a way to attach the ImageList to the DataGridView, but it doesn't have that ability.
Nazeeh
+1  A: 

The DataGridView control is meant to work with DataBinding. If you're not using DataBinding at all, I suggest you use a ListView control.

The ListView is optimized to displaying images. Furthermore, it is lighter in memory to instantiate than the DataGridView. Plus, the ListView control lets you change your view:

  1. ListView.View = View.Details;
  2. ListView.View = View.LargeIcons;
  3. ListView.View = View.List;
  4. ListView.View = View.SmallIcons;
  5. ListView.View = View.Tile.

These are the views you may experience within your Windows Explorer. Only only have to define yourself a LargeIcons ImageList, or a SmallIcons ImageList, or one of each, depending on the View you will allow for your user to see.

You may also display the GridLines as if it were a DataGridView, just to give the same aspect.

Will Marcouiller
hmm... I haven't really thought of that option. It should be quite easy to replace the dataGrid with a ListView. I'll give that a shot and see what happens. Thanks for the answer!
Nazeeh
@Nazeeh: Thanks!
Will Marcouiller
A: 

By the way, I've decided to do this in a different way. I've resorted to using Custom Painting to paint my icons in the cell. It worked out far better. The grid no longer eats up memory with this solution.

Using a ListView was possible but not very practical since it only supports putting icons in the first column. So I would have had to do custom painting anyway.

Nazeeh
You need to add subtitems if you want to add columns.
Will Marcouiller