我知道复制听起来很复杂,但请关注我:
您有一个带有VirtualMode = true.
选择一个项目,向下滚动以便所选项目超出可视区域,然后尝试将另一个项目添加到ListView。
你会看到它瞬间表现异常,看到一些闪烁。 如果你升级情况并试图快速添加很多项目(我每秒增加约20次),你会发现小问题变得非常大。它是周围闪烁和无效项目的组合。
我已经调查了这个问题,看起来ListView为所选项目生成了很多RetrieveVirtualItem
个事件(即使它显然不可见)。
似乎当我添加一个新项目(增加VirtualListSize)时,ListView首先尝试关注所选项目,然后返回上一个位置。
有没有人遇到同样的问题?
答案 0 :(得分: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));
}
}
}
}
答案 1 :(得分:1)
各种控件都有受保护的DoubleBuffered属性。您可以尝试从ListView派生自己的DBListView,并在其构造函数中将其DoubleBuffered属性设置为true。