我有一个继承的列表视图,当我点击列标题时会出现明显的闪烁。该列表在详细信息视图中。
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没有解决我的问题 我在托管列表视图的表单中添加了此代码,闪烁消失了
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
答案 0 :(得分:5)
通过将此代码添加到您的班级,您可以看到出现了什么问题:
protected override void OnHandleCreated(EventArgs e) {
Console.WriteLine("Listview window created");
base.OnHandleCreated(e);
}
运行程序并单击列标题,注意“输出”窗口。您会看到每次单击时,都会显示“已创建Listview窗口”消息。换句话说,每次排序时,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 :(得分: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