6

I have a ListView and i add items to it one-by-one with a loop
This ListView has CheckBoxes

In that loop i decide whether checkbox should be checked or not
Problem is if too many checkboxes should be checked adding items is too slow
Here is the code:

for (int i = 0; i < dt.Rows.Count; i++)
{
    DataRow drow = dt.Rows[i];

    // Only row that have not been deleted
    if (drow.RowState != DataRowState.Deleted && int.Parse(drow["season"].ToString()) != 0)
    {
        ListViewItem lvi = new ListViewItem(drow["episode_name"].ToString());

        lvi.SubItems.Add(drow["first_aired"].ToString());
        lvi.SubItems.Add(drow["episode"].ToString());
        lvi.SubItems.Add(drow["season"].ToString());
        lvi.SubItems.Add(drow["rating"].ToString());
        lvi.SubItems.Add(drow["episode_id"].ToString());
        if (bool.Parse(drow["watched"].ToString()))
        {
            lvi.Checked = true; //this is the problem, when i remove it, adding is fast
        }
        else {
            lvi.Checked = false;
        }
        episodesList.Items.Add(lvi);
    }
}

How can i make it faster?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
pedja
  • 3,285
  • 5
  • 36
  • 48
  • possible duplicate of [Adding Items to ListView too slow in C#](http://stackoverflow.com/questions/8570481/adding-items-to-listview-too-slow-in-c-sharp) – Ken White May 02 '13 at 17:14
  • I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders May 02 '13 at 17:31
  • @pedja Are you counting your Db call in your time as well or just the loop? – Yatrix May 02 '13 at 17:32
  • problem is i have listView_ItemCheck handler which updates database, so every time item gets checked i also updates database – pedja May 02 '13 at 17:37
  • Yah, that would DEFINITELY cause a problem if that is firing. See my comment in my answer for a workaround. – Yatrix May 02 '13 at 17:40

3 Answers3

9

On your listview, call .BeginUpdate() while you're loading in the results. After you're finished, call .EndUpdate(). This should speed it up as it's not trying to process and draw at the same time.

// wait to draw
episodesList.BeginUpdate();

// add your items

// draw everything
episodesList.EndUpdate();

EDIT

As Justin suggested, AddRange() could help some, but it probably won't eliminate your problem. See: How to speed adding items to a ListView?

EDIT #2

Since the event handlers are causing the issue, you can work around them by removing the handlers during load and re-adding them after. Or, you can use a global boolean _isLoading that you set before your load and after and then you can check _isLoading in your handlers so you don't make that trip to the Db. Removing/Readding the handler is probably the cleaner solution, though.

Removing event handlers

Community
  • 1
  • 1
Yatrix
  • 13,361
  • 16
  • 48
  • 78
  • Around ~100, it takes around 12sec to add – pedja May 02 '13 at 17:16
  • @pedja Have you tried populating ListViewItems to a list first then use the `listView.AddRange(mylist.ToArray());`? – Justin May 02 '13 at 17:20
  • I don't think it's much faster, @Justin. A little, but not a ton if this test is to be believed: http://stackoverflow.com/questions/9008310/how-to-speed-adding-items-to-a-listview – Yatrix May 02 '13 at 17:21
  • 2
    10 seconds to add around 100 items? Wha? There's something far wrong there, – Matthew Watson May 02 '13 at 17:22
  • when i remove that if/else that checks items it takes 0.5 seconds – pedja May 02 '13 at 17:23
  • @pedja Still seems way too slow. This may be hacky, but if we can't find another reason, maybe try checking them all after they've been added to the listview? – Yatrix May 02 '13 at 17:23
  • @pedja What happens if you move the value of the bool.parse to the checked flag? `lvi.Checked = bool.Parse(drow["watched"].ToString());` – Justin May 02 '13 at 17:27
  • @pedja: Do you have an event handler anywhere that is attached to the `ItemCheck` or `ItemChecked` events? – Matthew Watson May 02 '13 at 17:29
  • @MatthewWatson That event is attached to the listview - would that fire if they come in set that way? – Yatrix May 02 '13 at 17:30
  • @Yatrix I actually don't know. It's a good question. :) I doubt it though. – Matthew Watson May 02 '13 at 17:32
  • 3
    @ Matthew Watson thats exactly the problem – pedja May 02 '13 at 17:33
  • Ill try to remove it and see if its faster – pedja May 02 '13 at 17:34
  • yep, that is the problem, any way to fix it – pedja May 02 '13 at 17:35
  • @pedja You can detach the event while loading and reattach it when it's finished. You could also have a global _isLoading boolean variable checked in your handlers to skip the functionality inside them while the list is loading. Kinda hacky, tho. – Yatrix May 02 '13 at 17:37
1

Normally when you are making a large change, you should put mylistview.BeginUpdate() before your loop then mylistview.EndUpdate(). This will stop the list from updating until you have called the EndUpdate().

The Check box is probably causing the list to be redrawin slowing down the already large amount of work it has to do.

You could possibly try creating the list view items first then adding them to the listview using the AddRange() method. MSDN lists it as the perferred way.

Justin
  • 3,337
  • 3
  • 16
  • 27
0

It could be the string indexer lookups causing the slow down. Can you count on the indexes being static? You might try replacing the code with integer indexes and see if that improves performance.

Matt
  • 224
  • 1
  • 5