2009-10-20 74 views
4

我知道这听起来很复杂重现,但请跟我来:在VirtualMode C#的ListView闪烁

您有VirtualMode = true.

一个ListView选择一个项目,向下滚动,这样的选择的项目在视觉区域之外,然后尝试向ListView添加另一个项目。

你会看到一瞬间它表现异常,看到一些闪烁。 如果您将情况升级并尝试快速添加大量项目(我每秒添加大约20次),您会发现小问题变得非常大。这是闪烁和无效项目的组合。

我调查了这个问题,似乎ListView为所选项目生成了很多RetrieveVirtualItem事件(即使它显然不可见)。

这似乎是当我添加一个新项目(增加VirtualListSize)ListView首先尝试专注于选定的项目,然后返回到以前的位置。

有没有人遇到同样的问题?

回答

1

各种控件都有一个受保护的DoubleBuffered属性。您可以尝试从ListView派生自己的DBListView,并在其构造函数中将其DoubleBuffered属性设置为true。

+0

既然我已经发布了这个问题已经有一段时间了,我会尝试找到该项目并尝试解决您的问题。谢谢 – 2010-09-05 17:29:10

5

这里有一个解决此问题的派生类。

使用SetVirtualListSize()方法代替常规VirtualListSize

public class FlickerFreeListView : ListView 
{ 
    #region Static Functionality 

    private static FieldInfo _internalVirtualListSizeField; 

    static FlickerFreeListView() 
    { 
     _internalVirtualListSizeField = typeof(ListView).GetField("virtualListSize", System.Reflection.BindingFlags.NonPublic | BindingFlags.Instance); 

     if (_internalVirtualListSizeField == null) 
     { 
      string msg = "Private field virtualListSize in type System.Windows.Forms.ListView is not found. Workaround is incompatible with installed .NET Framework version, running without workaround."; 
      Trace.WriteLine(msg); 
     } 
    } 

    #endregion 


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

    internal IntPtr SendMessage(int msg, IntPtr wparam, IntPtr lparam) 
    { 
     return SendMessage(new HandleRef(this, this.Handle), msg, wparam, lparam); 
    } 

    public void SetVirtualListSize(int size) 
    { 
     // if workaround incompatible with current framework version (usually MONO) 
     if (_internalVirtualListSizeField == null) 
     { 
      VirtualListSize = size; 
     } 
     else 
     { 
      if (size < 0) 
      { 
       throw new ArgumentException("ListViewVirtualListSizeInvalidArgument"); 
      } 

      _internalVirtualListSizeField.SetValue(this, size); 
      if ((base.IsHandleCreated && this.VirtualMode) && !base.DesignMode) 
      { 
       SendMessage(0x102f, new IntPtr(size), new IntPtr(2)); 
      } 
     } 
    } 
} 
+0

谢谢你,但是我解决问题已经很长时间了。我无法再测试这个解决方案。我看到它有一些upvotes所以如果有人测试这个,它的工作,然后在这里写一个评论,所以我可以接受这个答案。 – 2013-04-29 19:49:06