2013-05-27 57 views
0

我有一個繼承ListView和有當我點擊列標題顯著閃爍。該清單在詳細視圖中。的ListView閃爍時排序

public ListViewEx() 
    { 
     this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true); 
     this.DoubleBuffered = true; 
    } 

    int sortColumn = -1; 
    protected override void OnColumnClick(ColumnClickEventArgs e) 
    { 
     if(e.Column != sortColumn) 
     { 
      sortColumn = e.Column; 
      this.Sorting = SortOrder.Ascending; 
     } 
     else 
     { 
      if(this.Sorting == SortOrder.Ascending) 
       this.Sorting = SortOrder.Descending; 
      else 
       this.Sorting = SortOrder.Ascending; 
     } 
     this.Sort(); 
    } 

當我填充列表時沒有閃爍。

 for(int i = 0; i < 10; i++) 
     { 
      ListViewItem lvi = new ListViewItem("this is column 1 " +i); 
      lvi.SubItems.Add("... 
      lvi.SubItems.Add("... 
      lvi.SubItems.Add("... 
      lvi.SubItems.Add("... 
      lvi.SubItems.Add("... 

      listViewEx1.Items .Add (lvi); 
     } 

編輯 WM_ERASEBKGND沒有解決我的問題。
我在表單中添加該代碼託管ListView和閃爍消失

protected override CreateParams CreateParams 
    { 
     get 
     { 
      CreateParams cp = base.CreateParams; 
      cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED 
      return cp; 
     } 
    } 

回答

5

你可以看到這裏發生了什麼錯誤通過將此代碼添加到您的類:

protected override void OnHandleCreated(EventArgs e) { 
    Console.WriteLine("Listview window created"); 
    base.OnHandleCreated(e); 
} 

運行你的程序並點擊列標題,注意輸出窗口。你會看到每次點擊時,你會看到「Listview window created」消息出現。換句話說,ListView窗口在每次排序時都會重新創建。那將會是總是閃爍,不管你用什麼雙緩衝。

這是由您的代碼分配ListView.Sorting屬性引起的。它的底層本機實現是一個樣式標誌,它只能在窗口創建時指定。所以當你改變它時,WinForms被迫重新創建窗口。閃爍是不可避免的副作用。

有一個更好的方法來做到這一點,你也可以通過使用它的ListViewItemSorter屬性實現控件的自定義排序方法。你所要做的就是提供一個實現IComparable接口的類。也可能讓ListView本身實現它。使你的代碼看起來像這樣和排序將是如絲般光滑:

using System; 
using System.Windows.Forms; 

class ListViewEx : ListView, System.Collections.IComparer { 
    public ListViewEx() { 
     this.DoubleBuffered = true; 
     this.ListViewItemSorter = this; 
    } 

    public int Compare(object x, object y) { 
     var item1 = (ListViewItem)x; 
     var item2 = (ListViewItem)y; 
     int compare = String.Compare(item1.SubItems[this.sortColumn].Text, item2.SubItems[this.sortColumn].Text); 
     if (sortOrder == SortOrder.Descending) compare = -compare; 
     return compare; 
    } 

    protected override void OnColumnClick(ColumnClickEventArgs e) { 
     if (e.Column != sortColumn) { 
      sortColumn = e.Column; 
      this.sortOrder = SortOrder.Ascending; 
     } 
     else { 
      if (this.sortOrder == SortOrder.Ascending) 
       this.sortOrder = SortOrder.Descending; 
      else 
       this.sortOrder = SortOrder.Ascending; 
     } 
     this.Sort(); 
    } 

    private int sortColumn = 0; 
    private SortOrder sortOrder = SortOrder.Ascending; 
} 
1
class ListViewNF : System.Windows.Forms.ListView 
{ 
    public ListViewNF() 
    { 
     //Activate double buffering 
     this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); 

     //Enable the OnNotifyMessage event so we get a chance to filter out 
     // Windows messages before they get to the form's WndProc 
     this.SetStyle(ControlStyles.EnableNotifyMessage, true); 
    } 

    protected override void OnNotifyMessage(Message m) 
    { 
     //Filter out the WM_ERASEBKGND message 
     if(m.Msg != 0x14) 
     { 
      base.OnNotifyMessage(m); 
     } 
    } 
} 

這是source

+0

如果你發現自己複製和答案對堆棧溢出的另一個問題粘貼,該問題可能是重複的。使用問題標籤下的「標誌」鏈接來表明這一點。 –

+0

@CodyGray:好的! – matzone