更新单个ListViewItem的文本时,如何防止ListView中出现闪烁?
我只想更新ListViewItem的文本,而不会看到任何闪烁。
这是我的更新代码(多次调用):
listView.BeginUpdate(); listViewItem.SubItems[0].Text = state.ToString(); // update the state listViewItem.SubItems[1].Text = progress.ToString(); // update the progress listView.EndUpdate();
我已经看到了一些解决方案,这些方案涉及重写组件的WndProc():
。
protected override void WndProc(ref Message m) { if (m.Msg == (int)WM.WM_ERASEBKGND) { m.Msg = (int)IntPtr.Zero; } base.WndProc(ref m); }
他们说这解决了问题,但就我而言,没有。我相信这是因为我在每个项目上都使用了图标。
解决方案
回答
如果我们只想更新文本,则只需直接设置更改后的SubItem的文本,而不是更新整个ListViewItem(我们尚未说明更新的方式)。
我们显示的覆盖等效于简单地覆盖OnPaintBackground,这将是一种"更正确"的托管方式来完成该任务,并且对单个项目无济于事。
如果我们仍然有问题,我们将需要澄清我们实际尝试过的操作。
回答
这是在黑暗中拍摄的照片,但是我们可以尝试对控件进行双重缓冲。
SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true)
回答
CommonControls 6(XP或者更高版本)中的ListView支持双缓冲。幸运的是,.NET将最新的CommonControl包装在系统上。若要启用双重缓冲,请将适当的Windows消息发送到ListView控件。
详细信息如下:
http://www.codeproject.com/KB/list/listviewxp.aspx
回答
为了结束这个问题,在为表单中的每个ListView或者任何其他ListView的派生控件加载表单时,应该调用一个帮助程序类。感谢" Brian Gillespie"提供的解决方案。
public enum ListViewExtendedStyles { /// <summary> /// LVS_EX_GRIDLINES /// </summary> GridLines = 0x00000001, /// <summary> /// LVS_EX_SUBITEMIMAGES /// </summary> SubItemImages = 0x00000002, /// <summary> /// LVS_EX_CHECKBOXES /// </summary> CheckBoxes = 0x00000004, /// <summary> /// LVS_EX_TRACKSELECT /// </summary> TrackSelect = 0x00000008, /// <summary> /// LVS_EX_HEADERDRAGDROP /// </summary> HeaderDragDrop = 0x00000010, /// <summary> /// LVS_EX_FULLROWSELECT /// </summary> FullRowSelect = 0x00000020, /// <summary> /// LVS_EX_ONECLICKACTIVATE /// </summary> OneClickActivate = 0x00000040, /// <summary> /// LVS_EX_TWOCLICKACTIVATE /// </summary> TwoClickActivate = 0x00000080, /// <summary> /// LVS_EX_FLATSB /// </summary> FlatsB = 0x00000100, /// <summary> /// LVS_EX_REGIONAL /// </summary> Regional = 0x00000200, /// <summary> /// LVS_EX_INFOTIP /// </summary> InfoTip = 0x00000400, /// <summary> /// LVS_EX_UNDERLINEHOT /// </summary> UnderlineHot = 0x00000800, /// <summary> /// LVS_EX_UNDERLINECOLD /// </summary> UnderlineCold = 0x00001000, /// <summary> /// LVS_EX_MULTIWORKAREAS /// </summary> MultilWorkAreas = 0x00002000, /// <summary> /// LVS_EX_LABELTIP /// </summary> LabelTip = 0x00004000, /// <summary> /// LVS_EX_BORDERSELECT /// </summary> BorderSelect = 0x00008000, /// <summary> /// LVS_EX_DOUBLEBUFFER /// </summary> DoubleBuffer = 0x00010000, /// <summary> /// LVS_EX_HIDELABELS /// </summary> HideLabels = 0x00020000, /// <summary> /// LVS_EX_SINGLEROW /// </summary> SingleRow = 0x00040000, /// <summary> /// LVS_EX_SNAPTOGRID /// </summary> SnapToGrid = 0x00080000, /// <summary> /// LVS_EX_SIMPLESELECT /// </summary> SimpleSelect = 0x00100000 } public enum ListViewMessages { First = 0x1000, SetExtendedStyle = (First + 54), GetExtendedStyle = (First + 55), } /// <summary> /// Contains helper methods to change extended styles on ListView, including enabling double buffering. /// Based on Giovanni Montrone's article on <see cref="http://www.codeproject.com/KB/list/listviewxp.aspx"/> /// </summary> public class ListViewHelper { private ListViewHelper() { } [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern int SendMessage(IntPtr handle, int messg, int wparam, int lparam); public static void SetExtendedStyle(Control control, ListViewExtendedStyles exStyle) { ListViewExtendedStyles styles; styles = (ListViewExtendedStyles)SendMessage(control.Handle, (int)ListViewMessages.GetExtendedStyle, 0, 0); styles |= exStyle; SendMessage(control.Handle, (int)ListViewMessages.SetExtendedStyle, 0, (int)styles); } public static void EnableDoubleBuffer(Control control) { ListViewExtendedStyles styles; // read current style styles = (ListViewExtendedStyles)SendMessage(control.Handle, (int)ListViewMessages.GetExtendedStyle, 0, 0); // enable double buffer and border select styles |= ListViewExtendedStyles.DoubleBuffer | ListViewExtendedStyles.BorderSelect; // write new style SendMessage(control.Handle, (int)ListViewMessages.SetExtendedStyle, 0, (int)styles); } public static void DisableDoubleBuffer(Control control) { ListViewExtendedStyles styles; // read current style styles = (ListViewExtendedStyles)SendMessage(control.Handle, (int)ListViewMessages.GetExtendedStyle, 0, 0); // disable double buffer and border select styles -= styles & ListViewExtendedStyles.DoubleBuffer; styles -= styles & ListViewExtendedStyles.BorderSelect; // write new style SendMessage(control.Handle, (int)ListViewMessages.SetExtendedStyle, 0, (int)styles); } }
回答
在.NET Winforms 2.0中,存在一个称为DoubleBuffered的受保护属性。
通过从ListView继承,可以将此受保护的属性设置为true。这将启用双重缓冲,而无需调用SendMessage。
设置DoubleBuffered属性与设置以下样式相同:
listview.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=94096