2011-12-28 57 views
0

我在MSDN中发现了一个解决方案,用于ListView排序... 但是,我发现代码需要花费太多时间来正确显示ListView,当点击列时... 所以我要求一个解决方案来加速它起来。我必须对包含超过10,000个项目的ListView进行排序。这是我整个代码...
如何更快排序ListView?


using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Collections; 
using System.Runtime.InteropServices; 

namespace ListViewSorter 
{ 
    class ListViewSorter 
    { 
     const Int32 HDF_SORTDOWN = 0x200; 
     const Int32 HDF_SORTUP = 0x400; 
     const Int32 HDI_FORMAT = 0x4; 
     const Int32 HDM_GETITEM = 0x120b; 
     const Int32 HDM_SETITEM = 0x120c; 
     const Int32 LVM_GETHEADER = 0x101f; 

     [DllImport("user32.dll", CharSet = CharSet.Auto)] 
     static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam); 

     [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessage")] 
     static extern IntPtr SendMessageLVCOLUMN(IntPtr hWnd, UInt32 msg, IntPtr wParam, ref LVCOLUMN lParam); 

     [StructLayout(LayoutKind.Sequential)] 
     public struct LVCOLUMN 
     { 
      public Int32 mask; 
      public Int32 cx; 
      [MarshalAs(UnmanagedType.LPTStr)] 
      public string pszText; 
      public IntPtr hbm; 
      public Int32 cchTextMax; 
      public Int32 fmt; 
      public Int32 iSubItem; 
      public Int32 iImage; 
      public Int32 iOrder; 
     } 
     public void SetSortIcon(ListView listview, int ColumnIndex) 
     { 
      IntPtr clmHdr = SendMessage(listview.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero); 
      SortOrder sorting = listview.Sorting; 
      for (int i = 0; i < listview.Columns.Count; i++) 
      { 
       IntPtr clmPtr = new IntPtr(i); 
       LVCOLUMN lvColumn = new LVCOLUMN(); 

       lvColumn.mask = HDI_FORMAT; 
       SendMessageLVCOLUMN(clmHdr, HDM_GETITEM, clmPtr, ref lvColumn); 
       if (sorting != SortOrder.None && i == ColumnIndex) 
       { 
        if (sorting == SortOrder.Ascending) 
        { 
         lvColumn.fmt &= ~HDF_SORTDOWN; 
         lvColumn.fmt |= HDF_SORTUP; 
        } 
        else 
        { 
         lvColumn.fmt &= ~HDF_SORTUP; 
         lvColumn.fmt |= HDF_SORTDOWN; 
        } 
       } 
       else 
       { 
        lvColumn.fmt &= ~HDF_SORTDOWN & ~HDF_SORTUP; 
       } 
       SendMessageLVCOLUMN(clmHdr, HDM_SETITEM, clmPtr, ref lvColumn); 
      } 
     } 
     public int SortColumn(ListView listview, int ColumnIndex, int sortColumn) 
     { 
      if (ColumnIndex != sortColumn) 
      { 
       sortColumn = ColumnIndex; 
       listview.Sorting = SortOrder.Ascending; 
      } 
      else 
      { 
       if (listview.Sorting == SortOrder.Ascending) 
        listview.Sorting = SortOrder.Descending; 
       else 
        listview.Sorting = SortOrder.Ascending; 
      } 
      SetSortIcon(listview, sortColumn); 
      listview.Sort(); 
      listview.ListViewItemSorter = new ListViewItemComparer(ColumnIndex, 
                   listview.Sorting); 
      return sortColumn; 
     } 
    } 
    class ListViewItemComparer : IComparer 
    { 
     private int col; 
     private SortOrder order; 
     public ListViewItemComparer() 
     { 
      col = 0; 
      order = SortOrder.Ascending; 
     } 
     public ListViewItemComparer(int column, SortOrder order) 
     { 
      col = column; 
      this.order = order; 
     } 
     public int Compare(object x, object y) 
     { 
      int returnVal; 
      try 
      { 
       System.DateTime firstDate = 
         DateTime.Parse(((ListViewItem)x).SubItems[col].Text); 
       System.DateTime secondDate = 
         DateTime.Parse(((ListViewItem)y).SubItems[col].Text); 
       returnVal = DateTime.Compare(firstDate, secondDate); 
      } 
      catch 
      { 
       returnVal = String.Compare(((ListViewItem)x).SubItems[col].Text, 
          ((ListViewItem)y).SubItems[col].Text); 
      } 
      if (order == SortOrder.Descending) 
       returnVal *= -1; 
      return returnVal; 
     } 

    } 
} 

谁能帮我出这个问题的?

回答

1

现在我想到的一种方法是使用od data-binding并设置VirtualModehttp://msdn.microsoft.com/en-us/library/system.windows.forms.listview.virtualmode.aspx。物业到true

这样做你西港岛线实现foliwing:

  • 贵大自定义数据data-layer自定义管理。换句话说,您可以对数据进行排序,并将其与listview绑定并且不排序listview项目。

  • listView.VirtualMode=true;将迫使listview控制只为那项进行UI可见创建列表视图项目。换句话说,如果您在datacollection中有10.000个项目,但在UI上我只能选择其中的15个,由于窗口尺寸,渲染和lustviewitem UI构件创建时间将仅花费15而不是10,000花费,就像它一样在你的情况。

希望这会有所帮助。

+0

我仍然需要一点提示如何使用虚拟模式的数据绑定...其实我不了解数据绑定.. – Writwick 2011-12-28 11:12:54

+1

@writz:这可以是有用的http://www.codeproject.com/ KB/list/ListView_DataBinding.aspx – Tigran 2011-12-28 11:38:58

+0

我发现一个[BindableListView控件](http://www.interact-sw.co.uk/utilities/bindablelistview/)...会好吗?? .. [我其实找出那里的代码] – Writwick 2011-12-28 12:51:24

0

我想你应该尝试定义数据类型而不是使用对象。迫使编译器找出dt需要额外的时间。