我想要的只是更新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); }
他们说这解决了问题,但在我的情况下却没有.我相信这是因为我在每个项目上使用图标.
接受的答案是有效的,但是相当冗长,并且从控制中得到(如在其他答案中提到的)只是为了实现双缓冲也有点过头了.但幸运的是我们有反思,如果我们愿意,也可以调用内部方法(但要确定你做了什么!).
将这种方法封装到扩展方法中,我们将获得一个非常短的类:
public static class ControlExtensions { public static void DoubleBuffering(this Control control, bool enable) { var method = typeof(Control).GetMethod("SetStyle", BindingFlags.Instance | BindingFlags.NonPublic); method.Invoke(control, new object[] { ControlStyles.OptimizedDoubleBuffer, enable }); } }
可以在我们的代码中轻松调用:
InitializeComponent(); myListView.DoubleBuffering(true); //after the InitializeComponent();
所有的闪烁都消失了.
我偶然发现了这个问题,由于这个事实,扩展方法应该(可能)更好:
public static void DoubleBuffered(this Control control, bool enable) { var doubleBufferPropertyInfo = control.GetType().GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic); doubleBufferPropertyInfo.SetValue(control, enable, null); }
要结束这个问题,这里有一个辅助类,当为表单中的每个ListView或任何其他ListView派生控件加载表单时,应该调用该辅助类.感谢"Brian Gillespie"提供解决方案.
public enum ListViewExtendedStyles { ////// LVS_EX_GRIDLINES /// GridLines = 0x00000001, ////// LVS_EX_SUBITEMIMAGES /// SubItemImages = 0x00000002, ////// LVS_EX_CHECKBOXES /// CheckBoxes = 0x00000004, ////// LVS_EX_TRACKSELECT /// TrackSelect = 0x00000008, ////// LVS_EX_HEADERDRAGDROP /// HeaderDragDrop = 0x00000010, ////// LVS_EX_FULLROWSELECT /// FullRowSelect = 0x00000020, ////// LVS_EX_ONECLICKACTIVATE /// OneClickActivate = 0x00000040, ////// LVS_EX_TWOCLICKACTIVATE /// TwoClickActivate = 0x00000080, ////// LVS_EX_FLATSB /// FlatsB = 0x00000100, ////// LVS_EX_REGIONAL /// Regional = 0x00000200, ////// LVS_EX_INFOTIP /// InfoTip = 0x00000400, ////// LVS_EX_UNDERLINEHOT /// UnderlineHot = 0x00000800, ////// LVS_EX_UNDERLINECOLD /// UnderlineCold = 0x00001000, ////// LVS_EX_MULTIWORKAREAS /// MultilWorkAreas = 0x00002000, ////// LVS_EX_LABELTIP /// LabelTip = 0x00004000, ////// LVS_EX_BORDERSELECT /// BorderSelect = 0x00008000, ////// LVS_EX_DOUBLEBUFFER /// DoubleBuffer = 0x00010000, ////// LVS_EX_HIDELABELS /// HideLabels = 0x00020000, ////// LVS_EX_SINGLEROW /// SingleRow = 0x00040000, ////// LVS_EX_SNAPTOGRID /// SnapToGrid = 0x00080000, ////// LVS_EX_SIMPLESELECT /// SimpleSelect = 0x00100000 } public enum ListViewMessages { First = 0x1000, SetExtendedStyle = (First + 54), GetExtendedStyle = (First + 55), } ////// Contains helper methods to change extended styles on ListView, including enabling double buffering. /// Based on Giovanni Montrone's article on 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); } }///
CommonControls 6中的ListView(XP或更新版本)支持双缓冲.幸运的是,.NET将最新的CommonControl包装在系统上.要启用双缓冲,请将相应的Windows消息发送到ListView控件.
以下是详细信息:http: //www.codeproject.com/KB/list/listviewxp.aspx
在.NET Winforms 2.0中,存在一个名为DoubleBuffered的受保护属性.
通过继承ListView,可以将此protected属性设置为true.这将启用双缓冲,而无需调用SendMessage.
设置DoubleBuffered属性与设置以下样式相同:
listview.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=94096