Wie Flimmern in Listview zu verhindern, wenn ein einzelnen ListViewItem Text zu aktualisieren?

StackOverflow https://stackoverflow.com/questions/87795

  •  01-07-2019
  •  | 
  •  

Frage

Alles was ich will ist ein ListViewItem Text whithout sieht jedes Flackern zu aktualisieren.

Dies ist mein Code für die Aktualisierung (so genannte mehrmals):

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

habe ich einige Lösungen zu sehen, die zwingende verwickeln der Komponente WndProc():

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

Sie sagen, es löst das Problem, aber in meinem Fall ist es tut nicht . Ich glaube, das liegt daran, dass ich Icons auf jedes Element verwendet wird.

War es hilfreich?

Lösung 2

Um diese Frage zu beenden, hier ist eine Hilfsklasse, die aufgerufen werden soll, wenn das Formular für jede Listview wird geladen oder irgendwelche andere Listview des abgeleiteten Steuer in Ihrem Formular. Dank „Brian Gillespie“ für die Lösung.

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

Andere Tipps

Die akzeptierte Antwort funktioniert, aber ist ziemlich lang, und von der Steuer Ableitung (wie in den anderen Antworten erwähnt) nur doppelte Pufferung zu ermöglichen, ist auch ein bisschen übertrieben. Aber zum Glück haben wir Reflexion und auch interne Methoden aufrufen können, wenn wir gerne (aber sicher sein, was Sie tun!).

Lassen Sie diesen Ansatz in eine Erweiterungsmethode Einkapselung, werden wir eine ganz kurze Klasse erhalten:

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

die einfach in unserem Code aufgerufen werden:

InitializeComponent();

myListView.DoubleBuffering(true); //after the InitializeComponent();

Und alle Flackern ist weg.

Update

Ich stolperte auf diese Frage und aufgrund dieser Tatsache, die Erweiterungsmethode sollte (vielleicht) besser sein:

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

Das Listview in Common 6 (XP oder höher) unterstützt doppelte Pufferung. Glücklicherweise wickelt .NET die neueste Common auf dem System. Um doppelte Pufferung zu aktivieren, die entsprechende Windows-Nachricht an das Listview-Steuerelement senden.

Hier sind die Details: http://www.codeproject.com/KB/list/listviewxp.aspx

In .NET WinForms 2.0 gibt es eine geschützte Eigenschaft namens DoubleBuffered.

Mit dem von Listview vererben, dann kann man diese geschützte Eigenschaft auf true gesetzt. Dadurch wird die doppelte Pufferung ermöglichen, ohne dass Sendmessage nennen.

die Eigenschaft DoubleBuffered Einstellung ist das gleiche wie die folgende Art setzen:

listview.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);

http://connect.microsoft.com/VisualStudio/feedback/ ViewFeedback.aspx? FeedbackID = 94096

Ich weiß, diese Frage ist ziemlich alt, aber da dies eine der ersten Suchergebnisse auf Google ist wollte ich meine Verlegenheit teilen.

Die einzige Art, wie ich 100% flackernden entfernen konnte, war die Antwort von Oliver (Erweiterungsklasse mit Double-Buffering) zu kombinieren und die BeignUpdate() und EndUpdate() Methoden verwenden.

Keiner von denen, auf ihre eigenen könnte fix für mich flackern. Zugegeben, ich benutze eine sehr komplexe Liste, dass ich in die Liste schieben muß und muß auch sie aktualisieren fast jede Sekunde.

Dies wird helfen:

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

Einfache Lösung ist folgende:

yourlistview.BeginUpdate ()

// Ist das Update von Hinzufügen und Entfernen von Elemente aus der Liste

yourlistview.EndUpdate ()

Wenn Sie nur den Text aktualisieren möchten, einfach die geändertene SubItem Text direkt eher eingestellt als die gesamten ListViewItem Aktualisierung (Sie haben nicht gesagt, wie Sie Ihren Updates tun).

Die Überschreibung Sie zeigen, entspricht einfach OnPaintBackground überschreiben, was ein „richtiger“ verwaltet Weg wäre, diese Aufgabe zu tun, und es ist nicht für ein einzelnes Element nicht helfen.

Wenn Sie immer noch Probleme haben, werden wir Klärungsbedarf auf, was Sie tatsächlich versucht haben.

Dies ist ein Schuss im Dunkeln, aber Sie könnten versuchen, die doppelte Kontrolle zu puffern.

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

Rufen Sie die Beginupdate () -Methode auf dem Listview, bevor eine der Listenansicht Artikel einstellen und dann nur nennen EndUpdate () nach alle Elemente hinzugefügt wurden.

Das wird das Flimmern stoppen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top