在ListView控件中闪烁(OwnerDraw,Virtual)

Yip*_*Yay 12 c# listview flicker ownerdrawn winforms

这个问题可能被视为使用ownerdraw和virtualmode在listview中闪烁的后续行动.

我有一个ListView控件Virtual mode,我尝试执行自定义绘图.项目渲染通过以下方法覆盖完成:

protected override void OnDrawItem(DrawListViewItemEventArgs eventArgs) 
Run Code Online (Sandbox Code Playgroud)

如引用的问题所述,自定义绘图会在鼠标悬停事件上引入闪烁.调试器告诉我这是由于过多的自定义绘制事件被触发而发生的.


现在 - 引用问题的接受答案告诉我们:

这是.NET的ListView中的一个错误,你不能通过双缓冲解决它.

  • 那么,这些信息有多可靠?这真的是个错误吗?或者我们可能只是试图切断部分消息并希望它不会改变可见行为?

  • 这是真的,如果我有我的所有者绘制例程ListViewin in Virtual Mode,我可以抑制这些Custom Draw事件并且只执行我的绘图WM_PAINT或者,也许,这在某些情况下是不正确的?

  • System.Windows.Forms控制能够在WM_PAINT不改变其初始行为的情况下完成所有绘画的前提条件是什么?

zmi*_*jko 10

至少对于的OnDrawItem双缓冲,这是不正确的是有一个bug,但它是一个有点傻:有,你可以设置一个受保护的属性,但是你需要重写的ListView.我创建了这种类:

public class MyListView : ListView
{
    public MyListView()
        : base()
    {
        DoubleBuffered = true;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在我的MyForm.Designer.cs文件中,我使用以下行更改ListView的实例化:

private ListView myListView;

this.myListView = new MyListView();
Run Code Online (Sandbox Code Playgroud)

OnDrawItem将像魅力一样工作!


det*_*ale 4

我在任何自定义渲染事件处理程序(DrawItem、DrawSubItem)中都看到了 ListView 控件的闪烁问题。我尝试了 BeginUpdate()/EndUpdate() 和双缓冲,但没有成功。我认为 .NET 会向自定义绘制列右侧的所有列触发额外的 WM_PAINT 。

不过,我发现这个解决方法适用于单个自定义渲染列 ListView。效果很好!

  1. 在列标题编辑器中,将自定义绘制的列设置为最后一列
  2. 更改您想要的位置的“DisplayIndex”

这应该可以解决鼠标悬停或运行时渲染时的闪烁问题。