Подтвердить что ты не робот

С# мерцающий список в обновлении

У меня есть список, который периодически обновляется (каждые 60 секунд). Мне было неприятно, что я получаю мерцание каждый раз, когда он устареет. Используемый метод состоял в том, чтобы очистить все элементы, а затем воссоздать их. Я решил вместо очистки элементов, которые я просто напишу прямо в ячейку с новым текстом. Это лучший подход или у кого-то есть лучшее решение.

4b9b3361

Ответ 1

Элемент управления ListView имеет проблему мерцания. Проблема заключается в том, что контрольная перегрузка обновления неправильно реализована так, что она действует как Refresh. Обновление должно привести к тому, что элемент управления будет перерисовывать только недопустимые регионы, тогда как Refresh перерисовывает элементы управления всей клиентской области. Поэтому, если вы должны изменить, скажем, цвет фона одного элемента в списке, тогда необходимо перекрасить только этот конкретный элемент. К сожалению, элемент управления ListView, по-видимому, имеет другое мнение и хочет перекрасить всю его поверхность всякий раз, когда вы общаетесь с одним элементом... даже если элемент в настоящее время не отображается. Итак, в любом случае, вы можете легко подавить мерцание, свернув свой собственный, следующим образом:

class ListViewNF : System.Windows.Forms.ListView
{
    public ListViewNF()
    {
        //Activate double buffering
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);

        //Enable the OnNotifyMessage event so we get a chance to filter out 
        // Windows messages before they get to the form WndProc
        this.SetStyle(ControlStyles.EnableNotifyMessage, true);
    }

    protected override void OnNotifyMessage(Message m)
    {
        //Filter out the WM_ERASEBKGND message
        if(m.Msg != 0x14)
        {
            base.OnNotifyMessage(m);
        }
    }
}

От: Geekswithblogs.net

Ответ 2

В дополнение к другим ответам многие элементы управления имеют метод [Begin|End]Update(), который можно использовать для уменьшения мерцания при редактировании содержимого - например:

    listView.BeginUpdate();
    try {
        // listView.Items... (lots of editing)
    } finally {
        listView.EndUpdate();
    }

Ответ 4

Превосходный вопрос и ответ Шторма. Здесь С++-порт его кода для всех, кто может заниматься реализацией С++/CLI.

#pragma once

#include "Windows.h" // For WM_ERASEBKGND

using namespace System;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;

public ref class FlickerFreeListView : public ListView
{
public:
    FlickerFreeListView()
    {
        //Activate double buffering
        SetStyle(ControlStyles::OptimizedDoubleBuffer | ControlStyles::AllPaintingInWmPaint, true);

        //Enable the OnNotifyMessage event so we get a chance to filter out 
        // Windows messages before they get to the form WndProc
        SetStyle(ControlStyles::EnableNotifyMessage, true);
    }

protected:
    virtual  void OnNotifyMessage(Message m) override
    {
        //Filter out the WM_ERASEBKGND message
        if(m.Msg != WM_ERASEBKGND)
        {
            ListView::OnNotifyMessage(m);
        }
    }

};

Ответ 5

Если это может помочь, следующий компонент решил мои проблесковые ошибки ListView с .NET 3.5

[ToolboxItem(true)]
[ToolboxBitmap(typeof(ListView))]
public class ListViewDoubleBuffered : ListView
{
    public ListViewDoubleBuffered()
    {
        this.DoubleBuffered = true;
    }
}

Я использую его в соединении с методами .BeginUpdate() и .EndUpdate(), где я выполняю манипуляции ListView.Items.

Я не понимаю, почему это свойство является защищенным... даже в .NET 4.5 (возможно, проблема с безопасностью)

Ответ 6

Простейшим решением, вероятно, будет использование

       listView.Items.AddRange(listViewItems.ToArray());

вместо

       foreach (ListViewItem listViewItem in listViewItems)
       {
           listView.Items.Add(listViewItem);
       }

Это работает лучше.

Ответ 7

Простое решение

yourlistview.BeginUpdate()

//Do your update of adding and removing item from the list

yourlistview.EndUpdate()

Ответ 8

Попробуйте установить свойство двойной буферизации в true.

Также вы можете использовать:

this.SuspendLayout();

//update control

this.ResumeLayout(False);

this.PerformLayout();

Ответ 9

Я знаю, что это очень старый вопрос и ответ. Однако это самый лучший результат при поиске "С++/cli listview flicker" - несмотря на то, что это даже не говорит о С++. Итак, здесь версия С++:

Я помещаю это в файл заголовка для своей основной формы, вы можете поместить его в другое место...

static void DoubleBuffer(Control^ control, bool enable) {
    System::Reflection::PropertyInfo^ info = control->GetType()->
        GetProperty("DoubleBuffered", System::Reflection::BindingFlags::Instance 
            | System::Reflection::BindingFlags::NonPublic);
    info->SetValue(control, enable, nullptr);
}

Если вам посчастливилось приземлиться здесь, чтобы найти аналогичный ответ для управляемого С++, это работает для меня.:)

Ответ 10

В Winrt Windows phone 8.1 вы можете установить следующий код, чтобы исправить эту проблему.

<ListView.ItemContainerTransitions>
    <TransitionCollection/>      
</ListView.ItemContainerTransitions>

Ответ 11

Вот мое быстрое исправление для реализации С#, которая не требует подклассификации видов списка и т.д.

Использует отражение, чтобы установить свойство DoubleBuffered, чтобы попробовать в конструкторе форм.

    lvMessages
        .GetType()
        .GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
        .SetValue(lvMessages, true, null);