views:

57

answers:

1

For some time I've been having difficulties with one of my ListView's being populated very slowly (3000 entries in 15 secs or so (with 5 columns). It was driving me mad since sql query returned values in less then second. I tracked it down to ListViewColumnSorter being the slowdown. When i commented out:

private ListViewColumnSorter lvwColumnSorterKontrahenci = new ListViewColumnSorter();
listViewKontrahenci.ListViewItemSorter = lvwColumnSorterKontrahenci;

ListView got populated within 1 second. I always thought that when i attach column sorter it starts it's job when i actually execute it by clicking on column header.

 private void listViewKontrahenci_ColumnClick(object sender, ColumnClickEventArgs e) {
        ListViewColumnSorter.columnClick(listViewKontrahenci, ref lvwColumnSorterKontrahenci, sender, e, headerIcons);
}

I thought that until I start it at least once like that it wouldn't be a problem.

Code for my listview sorting:

    public static void columnClick(ListView varListView, ref ListViewColumnSorter lvwColumnSorter, object sender, ColumnClickEventArgs e, ImageList headerImages) {
        //get list view header
        IntPtr hHeader = SendMessage(varListView.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero);
        SendMessage(hHeader, HDM_SETIMAGELIST, IntPtr.Zero, headerImages.Handle);
        SortOrder Order = SortOrder.Descending;
        //format icons
        HDITEM hd = new HDITEM {
                                   mask = HDI_IMAGE | HDI_FORMAT
                               };
        for (int i = 0; i < varListView.Columns.Count; i++) {
            //    if (i != e.Column) {
            hd.fmt = HDF_LEFT | HDF_STRING;
            hd.iImage = -1;
            SendMessage(hHeader, HDM_SETITEM, new IntPtr(i), ref hd);
            //    }
        }
        hd.fmt = HDF_LEFT | HDF_STRING | HDF_BITMAP_ON_RIGHT;
        //ListViewHelper.enableDoubleBuffer(varListView);
        if (Order != SortOrder.None) {
            hd.fmt |= HDF_IMAGE;
        }
        if (e.Column == lvwColumnSorter.SortColumn) {
            if (lvwColumnSorter.Order == SortOrder.Ascending) {
                hd.iImage = 0;
                lvwColumnSorter.Order = SortOrder.Descending;
            } else {
                hd.iImage = 1;
                lvwColumnSorter.Order = SortOrder.Ascending;
            }
        } else {
            hd.iImage = 1;
            lvwColumnSorter.SortColumn = e.Column;
            lvwColumnSorter.Order = SortOrder.Ascending;
        }
        SendMessage(hHeader, HDM_SETITEM, new IntPtr(e.Column), ref hd);
        varListView.Sort();
    }

So what would be your advice? To detach / attach sorter every time I populate ListView or is there some better way?

+1  A: 

It is going to sort the items each time you add an item. Either temporarily disable the sort or use the Items.AddRange() method to add a bunch of items at the same time. And consider Begin/EndUpdate() when you add one at a time.

Hans Passant
I was using `varListView.Items.AddRange(new[] {item});` and performance was the same. I was using `Begin/EndUpdate` as well. Right now I decided to use `varListView.ListViewItemSorter = null;` right before filling the listView and `varListView.ListViewItemSorter = listViewColumnSorter;` when i'm done with it. It works a lot better now.
MadBoy
You are supposed to actually add a range of items, one doesn't help. Store them in a list first.
Hans Passant