質問

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) 以外は何も使用しておらず、作成時にラベルとテキストボックスをコントロール リスト (DisposeAndClearControls() で参照) に追加します。私はdetailTable.Controlsを反復してそのように処分しようとしましたが、コントロールの半分が欠けているようでした(デバッガーでステップスルーすることで決定されました)。このようにして、すべてを理解していることがわかります。

描画パフォーマンスを向上させるための提案に興味がありますが、特に複数の選択によるパフォーマンスの低下の原因は何ですか。

役に立ちましたか?

解決 3

私は、各選択の変更に私のユーザーコントロールの新しいバージョンを構築するために含むフォームを変更しました。これは、古いものを処分し、新しいものを構築します。これがうまく行っているようです。私はもともと、とにかく一つだけのパフォーマンス上の理由を再利用して行ってよ。明らかにそれは、パフォーマンスは向上しません。私は古いものを廃棄して、新しいものを作成した場合、パフォーマンスが問題ではありません。

TableLayoutPanelはしかし、そのようにリークすること。

この不幸

他のヒント

あなたが動的に行を追加または削除する場合は特に...

ただ、TableLayoutPanelから継承したカスタムコントロールを使用して素晴らしい作品、真の上DoubleBufferedプロパティを設定します。

public CustomLayout()
{
   this.DoubleBuffered = true;
   InitializeComponent();
}

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

どうやら、Clear メソッドはコントロールを明示的に破棄しません (TableLayout からコントロールを削除したという事実は、コントロールの使用が完了したことを意味するわけではないため、これは当然のことです)。TableLayout から子コントロールを削除すると、クリーンアップ ルーチンによる破棄が妨げられます。 LayoutTable 自体が破棄されたときに子が返されます (LayoutTable 自体は単に子について認識しなくなっただけです)。

私のおすすめ:を削除します 詳細Table.Controls.Clear(); 行で、親テーブルからdetailTable自体を削除します。 コントロール コレクションを削除して破棄し、次のラウンドのために新しい TableLayout を作成します。また、DisposeAndClearControls メソッドは必要ないため、完全に削除します。私の経験では、それはうまくいきました。

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

私は同じ問題に直面し、あまり変更することなく、良い方法を見つけます:

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

残念ながら、私が提供できる唯一のアドバイスは、あなたのコントロールの配置を自分の世話をすることです。私の経験.NET TableLayoutPanelでは、非常に有用であるが、何かをリークしているし、それが成長して(と、それはどちらか、この時点に到達するために、細胞の無理数を取ることはありません)unusably遅くなります。この動作は、同様に、デザイナーで見ることができます。

TableLayoutPanel.Controls.Clearは()私のために正常に動作します、多分私は、表示されるのとは別のタブからそれをクリアしているので。

List<Control> controls = new List<Control>();
foreach (Control control in tableLayoutPanelEnderecoDetalhes.Controls)
{
    controls.Add(control);
}

foreach (Control control in controls)
{
    control.Dispose();
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top