51

私が望むのは、ちらつきを見ずに ListViewItem のテキストを更新することだけです。

これは更新用の私のコードです(数回呼び出されます):

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

コンポーネントのオーバーライドを含むいくつかのソリューションを見てきましたWndProc():

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

彼らはそれが問題を解決すると言いますが、私の場合はそうではありませんでした。これは、すべてのアイテムにアイコンを使用しているためだと思います。

4

10 に答える 10

76

受け入れられた答えは機能しますが、非常に長く、ダブルバッファリングを有効にするためだけにコントロールから派生する (他の回答で述べたように) のも少しやり過ぎです。しかし幸いなことに、リフレクションがあり、必要に応じて内部メソッドを呼び出すこともできます (ただし、何をするかを確認してください!)。

このアプローチを拡張メソッドにカプセル化すると、非常に短いクラスが得られます。

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

コード内で簡単に呼び出すことができます。

InitializeComponent();

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

そして、すべてのちらつきがなくなりました。

アップデート

私はこの質問に出くわしました。この事実により、拡張メソッドは(おそらく)より良いはずです:

public static void DoubleBuffered(this Control control, bool enable)
{
    var doubleBufferPropertyInfo = control.GetType().GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
    doubleBufferPropertyInfo.SetValue(control, enable, null);
}
于 2013-03-07T10:11:07.240 に答える
52

この質問を終了するには、フォーム内の各 ListView またはその他の ListView の派生コントロールに対してフォームが読み込まれるときに呼び出す必要があるヘルパー クラスを次に示します。解決策を提供してくれた「Brian Gillespie」に感謝します。

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);
    }
}
于 2008-10-02T14:55:18.077 に答える
11

CommonControls 6 (XP 以降) の ListView は、ダブル バッファリングをサポートしています。幸いなことに、.NET はシステム上の最新の CommonControls をラップします。ダブル バッファリングを有効にするには、適切な Windows メッセージを ListView コントロールに送信します。

詳細は次のとおりです 。 http://www.codeproject.com/KB/list/listviewxp.aspx

于 2008-09-19T17:22:04.757 に答える
10

.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

于 2010-10-07T23:35:06.020 に答える
2

この質問がかなり古いことは知っていますが、これは Google での最初の検索結果の 1 つであるため、修正を共有したいと思いました。

ちらつきを 100% 除去できる唯一の方法は、Oliver からの回答 (拡張クラスとダブル バッファリング) を組み合わせてメソッドBeignUpdate()EndUpdate()メソッドを使用することでした。

どちらも、ちらつきを自分で修正することはできませんでした。確かに、私はリストにプッシュする必要があり、ほぼ毎秒更新する必要がある非常に複雑なリストを使用しています。

于 2015-04-03T19:58:10.233 に答える
1

これは役立ちます:

class DoubleBufferedListView : System.Windows.Forms.ListView
{
    public DoubleBufferedListView()
        :base()
    {
        this.DoubleBuffered = true;
    }
}
于 2012-04-27T14:26:27.280 に答える
0

簡単な解決策は次のとおりです。

yourlistview.BeginUpdate()

//リストのアイテムの追加と削除の更新を行います

yourlistview.EndUpdate()

于 2014-08-20T09:51:08.947 に答える
0

テキストのみを更新したい場合は、ListViewItem 全体を更新するのではなく、変更された SubItem のテキストを直接設定するだけです (更新の方法については言及していません)。

あなたが示すオーバーライドは、単に OnPaintBackground をオーバーライドすることと同等です。これは、そのタスクを実行するための「より正しい」管理された方法であり、単一のアイテムには役立ちません。

それでも問題が解決しない場合は、実際に何を試したかを明確にする必要があります。

于 2008-09-17T21:26:40.357 に答える
0

これは暗闇でのショットですが、コントロールのダブル バッファリングを試すことができます。

SetStyle(
  ControlStyles.AllPaintingInWmPaint |
  ControlStyles.UserPaint |
  ControlStyles.DoubleBuffer, true)
于 2008-09-17T21:27:57.827 に答える
0

リスト ビュー アイテムを設定する前に、ListView で BeginUpdate() メソッドを呼び出し、すべてのアイテムが追加された後にのみ EndUpdate() を呼び出します。

これでちらつきが止まります。

于 2012-09-18T16:08:27.077 に答える