5

2 列の TableLayoutPanel を含むユーザー コントロールがあり、別のコントロールで選択された項目の詳細を表示する行を動的に追加するコマンドを受け入れます。したがって、ユーザーは他のコントロール (DataGridView) で行を選択し、DataGridView の SelectedItemChanged イベント ハンドラーで詳細コントロールをクリアしてから、新しく選択した項目のすべての行を再生成します (詳細はまったく異なる場合があります)。前に選択した項目から表示されます)。これはしばらくの間うまく機能します。しかし、選択した項目から別の項目に長時間移動し続けると、更新が非常に遅くなります (それぞれ 3 ~ 5 秒)。それは、すべてを適切に処分していないように聞こえますが、何が欠けているのかわかりません。TableLayoutPanel をクリアするためのコードは次のとおりです。

private readonly List<Control> controls;

public void Clear()
{
    detailTable.Visible = false;
    detailTable.SuspendLayout();
    SuspendLayout();
    detailTable.RowStyles.Clear();
    detailTable.Controls.Clear();
    DisposeAndClearControls();
    detailTable.RowCount = 0;
    detailTable.ColumnCount = 2;
}

private void DisposeAndClearControls()
{
    foreach (Control control in controls)
    {
        control.Dispose();
    }
    controls.Clear();
}

そして、次の詳細表示のために必要なすべてのコントロールを TableLayoutPanel にロードし終えたら、次のように呼び出します。

public void Render()
{
    detailTable.ResumeLayout(false);
    detailTable.PerformLayout();
    ResumeLayout(false);
    detailTable.Visible = true;
}

私は TableLayoutPanel 内でラベル (および TextBox を使用することはめったにありません) 以外は使用しておらず、ラベルと TextBoxes を作成時にコントロール リスト (DisposeAndClearControls() で参照) に追加しています。detailTable.Controls を反復処理してそのように破棄しようとしましたが、コントロールの半分が欠けているように見えました (デバッガーでステップスルーすることによって決定されます)。このようにして、私はそれらすべてを取得していることを知っています。

描画パフォーマンスを改善するための提案に興味がありますが、特に複数の選択での劣化の原因は何ですか.

4

7 に答える 7

10

TableLayoutPanel から継承するカスタム コントロールを使用し、DoubleBuffered プロパティを true に設定するだけで、特に行を動的に追加または削除する場合にうまく機能します。

public CustomLayout()
{
   this.DoubleBuffered = true;
   InitializeComponent();
}
于 2009-06-18T13:56:18.500 に答える
4

TableLayout でも同様の問題がありました。TableLayout.Controls.Clear()メソッドを使用した場合、子コントロールが破棄されることはありませんでしたが、TableLayout をクリアせずに単にドロップすると、リークが停止しました。振り返ってみると、ある種のリークを防ぐために Clear メソッドを使用したのはおかしいです。

どうやら、 Clear メソッドはコントロールを明示的に破棄しません (TableLayout からコントロールを削除したからといって、コントロールが終了したわけではないため、これは理にかなっています)。 LayoutTable 自体が破棄されたときの子 (単純に、子についてはわかりません)。

私の推奨事項: detailTable.Controls.Clear();を削除します。親のControlsコレクションから detailTable 自体を削除して破棄し、次のラウンドのためにまったく新しい TableLayout を作成します。また、DisposeAndClearControls メソッドは必要ないため、完全に失います。私の経験では、うまく機能しました。

これにより、ユーザー コントロール全体をリサイクルする必要がなくなり、その中の TableLayout のみをリサイクルすることができます。

于 2010-02-25T16:33:27.607 に答える
1

私は同じ問題に直面し、あまり変更せずに良い方法を見つけました:

VB.netで

Dim tp As Type = tlpMyPanel.GetType().BaseType
Dim pi As Reflection.PropertyInfo = _
    tp.GetProperty("DoubleBuffered", _ 
    Reflection.BindingFlags.Instance _
    Or Reflection.BindingFlags.NonPublic)
pi.SetValue(tlpMyPanel, True, Nothing)

またはC#で:

Type tp = tlpMyPanel.GetType().BaseType;
System.Reflection.PropertyInfo pi = 
    tp.GetProperty("DoubleBuffered",
    System.Reflection.BindingFlags.Instance 
    | System.Reflection.BindingFlags.NonPublic);
pi.SetValue(tlpMyPanel, true, null);
于 2013-03-14T18:46:46.207 に答える
0

TableLayoutPanel.Controls.Clear() は私にとっては問題なく動作します。おそらく、表示されているタブとは別のタブからクリアしているためです。

于 2012-05-04T20:29:36.700 に答える