it-swarm-tr.com

Tek bir ListViewItem metnini güncellerken ListView'da titremeyi nasıl önleyebilirim?

Tek istediğim, herhangi bir titremeyi görmeden bir ListViewItem'in metnini güncellemektir.

Bu güncelleme kodum (birkaç kez denir):

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

Bileşenin WndProc(): işlevini geçersiz kılmakla ilgili bazı çözümler gördüm.

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

Sorunu çözdüğünü söylüyorlar, fakat benim durumumda olmadı . Bunun her öğede simgeler kullandığım için olduğuna inanıyorum.

46
Jonas

Bu soruyu sonlandırmak için, burada her ListView veya formunuzdaki diğer bir ListView'ın türetilmiş kontrolü için form yüklenirken çağrılması gereken bir yardımcı sınıf vardır. Çözüm verdiğiniz için "Brian Gillespie" ye teşekkürler.

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

Kabul edilen cevap işe yarar, ancak oldukça uzundur ve kontrolden türetmek (diğer cevaplarda belirtildiği gibi) sadece çift tamponlamayı etkinleştirmek için biraz fazla abartılmıştır. Ama neyse ki yansıması var ve eğer istersen içsel yöntemleri de söyleyebiliriz (ama ne yaptığınızdan emin olun!).

Bu yaklaşımı bir uzatma yöntemine dahil ederek oldukça kısa bir sınıf alacağız:

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

Kolayca bizim kodumuzda aranabilir:

InitializeComponent();

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

Ve tüm titremeler gitti.

Güncelleştirme

Bu soruya rastladım ve bu nedenle, uzatma yöntemi daha iyi olmalı

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

CommonControls 6'daki (XP veya daha yeni) ListView çift tamponlamayı destekler. Neyse ki, .NET sistemdeki en yeni CommonControl'leri tamamlıyor. Çift arabelleklemeyi etkinleştirmek için, uygun Windows mesajını ListView kontrolüne gönderin.

İşte detaylar: http://www.codeproject.com/KB/list/listviewxp.aspx

11
Brian Gillespie

.NET Winforms 2.0'da, DoubleBuffered adlı korumalı bir özellik vardır.

ListView'den devralarak, kişi bu korumalı özelliği true olarak ayarlayabilir. Bu SendMessage'ı aramanıza gerek kalmadan çift arabelleklemeyi etkinleştirir.

DoubleBuffered özelliğini ayarlamak, aşağıdaki stili ayarlamakla aynıdır:

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

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

10
Rolf Kristensen

Bu sorunun oldukça eski olduğunu biliyorum, ancak bu Google’daki ilk arama sonuçlarından biri olduğundan düzeltimi paylaşmak istedim.

% 100 titreyen titremeyi kaldırabilmemin tek yolu, cevabı Oliver (çift tamponlama ile genişletme sınıfı) ve BeignUpdate() ve EndUpdate() yöntemlerini kullanarak birleştirmekti.

Kendi başlarına hiçbiri benim için titremeyi düzeltemedi .. .. Kabul ediyorum, listeye girmem gereken ve neredeyse her saniye güncellemem gereken çok karmaşık bir liste kullanıyorum.

2
T4cC0re

bu yardımcı olacak:

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

Yalnızca metni güncellemek istiyorsanız, ListViewItem'in tamamını güncellemek yerine doğrudan değiştirilen SubItem'in metnini ayarlayın (güncellemelerinizi nasıl yaptığınızı söylemediniz).

Gösterdiğiniz geçersiz kılma, bu görevi gerçekleştirmenin "daha doğru" bir şekilde yönetilen bir yolu olacak olan OnPaintBackground'ı geçersiz kılmaya eşdeğerdir ve tek bir öğe için yardımcı olmaz.

Hala sorunlarınız varsa, gerçekte ne denemeniz gerektiği konusunda açıklamaya ihtiyacımız var.

0
ctacke

Bu karanlıkta bir çekim, ancak kontrolü çift tamponlamayı deneyebilirsiniz.

SetStyle(
  ControlStyles.AllPaintingInWmPaint |
  ControlStyles.UserPaint |
  ControlStyles.DoubleBuffer, true)
0
Ed S.

Liste görünümü öğelerinin herhangi birini ayarlamadan önce ListView'de BeginUpdate () yöntemini çağırın ve ardından tüm öğeler eklendikten sonra yalnızca EndUpdate () öğesini çağırın.

Bu titremeyi durduracak.

0
Mike

Basit çözüm şudur:

yourlistview.BeginUpdate ()

// Listeye öğe ekleme ve çıkarma güncellemenizi yapın

yourlistview.EndUpdate ()

0
jaiveeru