Как предотвратить мерцание в ListView при обновлении одного текста ListViewItem?

Все, что я хочу, – это обновить текст ListViewItem без видимых мерцаний.

Это мой код для обновления (называется несколько раз):

listView.BeginUpdate(); listViewItem.SubItems[0].Text = state.ToString(); // update the state listViewItem.SubItems[1].Text = progress.ToString(); // update the progress listView.EndUpdate(); 

Я видел некоторые решения, которые include в себя переопределение компонента WndProc():

 protected override void WndProc(ref Message m) { if (m.Msg == (int)WM.WM_ERASEBKGND) { m.Msg = (int)IntPtr.Zero; } base.WndProc(ref m); } 

Говорят, это решает проблему, но в моем случае это не так . Я считаю, что это потому, что я использую значки для каждого элемента.

Принятый ответ работает, но довольно длинный, и из-за контроля (как упоминалось в других ответах) просто для двойной буферизации также немного переборщил. Но, к счастью, у нас есть reflection, и мы можем также вызвать внутренние методы, если нам нравится (но не забудьте, что вы делаете!).

Инкапсулируя этот подход в метод расширения, мы получим довольно короткий class:

 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 }); } } 

Который легко можно назвать внутри нашего кода:

 myListView.DoubleBuffering(true); 

И все мерцание исчезло.

Обновить

Я наткнулся на этот вопрос, и из-за этого метод расширения должен (возможно) быть лучше:

 public static void DoubleBuffered(this Control control, bool enable) { var doubleBufferPropertyInfo = control.GetType().GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic); doubleBufferPropertyInfo.SetValue(control, enable, null); } 

Чтобы закончить этот вопрос, вот вспомогательный class, который следует вызывать, когда форма загружается для каждого ListView или любого другого элемента управления ListView в вашей форме. Спасибо «Брайан Гиллеспи» за то, что он дал решение.

 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); } } 

ListView в CommonControls 6 (XP или новее) поддерживает двойную буферизацию. К счастью, .NET обматывает новейшие CommonControls в системе. Чтобы включить двойную буферизацию, отправьте соответствующее сообщение Windows в элемент управления ListView.

Вот подробности: http://www.codeproject.com/KB/list/listviewxp.aspx

В .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

Я знаю, что этот вопрос довольно старый, но поскольку это один из первых результатов поиска в Google, я хотел поделиться своим исправлением.

Единственный способ удалить мерцание на 100% состоял в том, чтобы объединить ответ с Оливером (class расширения с двойной буферизацией) и использовать BeignUpdate() и EndUpdate() .

Ни один из тех, кто по своему усмотрению, не мог пометить мерцание для меня. Конечно, я использую очень сложный список, который мне нужно нажать в список, а также обновить его почти каждую секунду.

это поможет:

 class DoubleBufferedListView : System.Windows.Forms.ListView { public DoubleBufferedListView() :base() { this.DoubleBuffered = true; } } 

Если вы хотите только обновить текст, просто установите текст измененного SubItem напрямую, а не обновите весь ListViewItem (вы не сказали, как вы делаете свои обновления).

Переопределение, которое вы показываете, эквивалентно просто переопределению OnPaintBackground, что было бы «более правильным» способом для выполнения этой задачи, и это не поможет ни одному элементу.

Если у вас все еще есть проблемы, нам нужно уточнить, что вы на самом деле пытались.

Это выстрел в темноте, но вы можете попробовать удвоить буферизацию элемента управления.

 SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true) 

Вызовите метод BeginUpdate () в ListView перед настройкой любого из элементов представления списка, а затем вызовите EndUpdate () после того, как все элементы были добавлены.

Это остановит мерцание.

Простым решением является следующее:

yourlistview.BeginUpdate ()

// Делаем ваше обновление добавления и удаления элемента из списка

yourlistview.EndUpdate ()

  • Конструктор UserControl с параметрами в C #
  • как программно перемещать мышь, щелкнуть, правым кликом и нажатием клавиши и т. д. в winform и wpf?
  • Двойная буферизация Winforms
  • Как загрузить изображение с SQL Server в окно изображения?
  • Добавьте несколько изображений в тело электронной почты (inline) с помощью приложения windows c #
  • Может ли библиотека classов иметь файл App.config?
  • Управление объемом приложения: по идентификатору процесса
  • Привести другие процессы Окно на передний план, если у него есть ShowInTaskbar = false
  • Как создавать и подключать пользовательские кнопки / элементы управления с линиями, используя формы окон
  • Лучшая практика для создания многоязычного приложения в C # / WinForms?
  • Закругленные края в кнопке C # (WinForms)
  • Давайте будем гением компьютера.