Tout ce que je veux, c'est mettre à jour le texte d'un ListViewItem sans voir de scintillement.
Voici mon code de mise à jour (appelé plusieurs fois):
listView.BeginUpdate();
listViewItem.SubItems[0].Text = state.ToString(); // update the state
listViewItem.SubItems[1].Text = progress.ToString(); // update the progress
listView.EndUpdate();
J'ai vu des solutions qui impliquent de surcharger la fonction WndProc():
du composant
protected override void WndProc(ref Message m)
{
if (m.Msg == (int)WM.WM_ERASEBKGND)
{
m.Msg = (int)IntPtr.Zero;
}
base.WndProc(ref m);
}
Ils disent que cela résout le problème, mais dans mon cas, il ne l'a pas fait . Je pense que c’est parce que j’utilise des icônes pour chaque élément.
Pour terminer cette question, voici une classe d'assistance qui doit être appelée lors du chargement du formulaire pour chaque contrôle ListView ou tout autre contrôle dérivé de ListView dans votre formulaire. Merci à "Brian Gillespie" pour avoir donné la solution.
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);
}
}
La réponse acceptée fonctionne, mais est assez longue, et dériver du contrôle (comme mentionné dans les autres réponses) juste pour activer la double mise en mémoire tampon est aussi un peu exagéré. Mais heureusement, nous avons de la réflexion et pouvons aussi faire appel à des méthodes internes si nous le souhaitons (mais soyez sûr de ce que vous faites!).
Encapsulant cette approche dans une méthode d'extension, nous aurons une classe assez courte:
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 });
}
}
Ce qui peut facilement être appelé dans notre code:
InitializeComponent();
myListView.DoubleBuffering(true); //after the InitializeComponent();
Et tout le scintillement est parti.
Je suis tombé sur cette question et de ce fait, la méthode d'extension devrait (peut-être) être:
public static void DoubleBuffered(this Control control, bool enable)
{
var doubleBufferPropertyInfo = control.GetType().GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
doubleBufferPropertyInfo.SetValue(control, enable, null);
}
Le ListView dans CommonControls 6 (XP ou plus récent) prend en charge le double buffering. Heureusement, .NET encapsule les derniers CommonControls sur le système. Pour activer la double mise en mémoire tampon, envoyez le message Windows approprié au contrôle ListView.
Voici les détails: http://www.codeproject.com/KB/list/listviewxp.aspx
Dans .NET Winforms 2.0, il existe une propriété protégée appelée DoubleBuffered.
En héritant de ListView, vous pouvez définir cette propriété protégée sur true. Cela activera la double mise en mémoire tampon sans qu'il soit nécessaire d'appeler SendMessage.
La définition de la propriété DoubleBuffered est identique à la définition du style suivant:
listview.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
http://connect.Microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=94096
Je sais que cette question est assez ancienne, mais parce que c’est l’un des premiers résultats de recherche sur Google, je voulais partager ma solution.
La seule façon de supprimer le scintillement à 100% était de combiner la réponse d'Oliver (classe d'extension avec double tampon) et d'utiliser les méthodes BeignUpdate()
et EndUpdate()
.
Aucune de ces solutions ne pourrait résoudre le scintillement pour moi… __. D'accord, j'utilise une liste très complexe, que je dois intégrer à la liste et la mettre à jour presque toutes les secondes.
cA aidera:
class DoubleBufferedListView : System.Windows.Forms.ListView
{
public DoubleBufferedListView()
:base()
{
this.DoubleBuffered = true;
}
}
Si vous souhaitez uniquement mettre à jour le texte, définissez simplement le texte du sous-élément modifié directement plutôt que de mettre à jour l'intégralité de ListViewItem (vous n'avez pas expliqué comment vous réalisiez vos mises à jour).
La substitution que vous affichez équivaut à remplacer simplement OnPaintBackground, ce qui constituerait une méthode gérée "plus correcte" pour effectuer cette tâche, qui ne servira à rien pour un seul élément.
Si vous avez toujours des problèmes, nous aurons besoin d'éclaircissements sur ce que vous avez réellement essayé.
C'est un coup dans le noir, mais vous pouvez essayer de mettre en double tampon le contrôle.
SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.DoubleBuffer, true)
Appelez la méthode BeginUpdate () sur ListView avant de définir l'un des éléments de la vue liste, puis appelez uniquement EndUpdate () une fois tous les éléments ajoutés.
Cela arrêtera le scintillement.
yourlistview.BeginUpdate ()
// Faites votre mise à jour pour ajouter et supprimer des éléments de la liste
yourlistview.EndUpdate ()