2011-12-28 56 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需要額外的時間。