Frage

Ich habe eine Benutzersteuerung, die einen 2-Säulen-Table enthält und nimmt Befehle dynamisch Zeilen hinzufügen Details eines Elements in einem separaten Steuer ausgewählt angezeigt werden soll. So wählt der Benutzer eine Zeile in der anderen Steuerung (ein Datagridview) und in der SelectedItemChanged Ereignishandler für das Datagridview lösche ich die Kontrolle Detail und dann regenerieren alle Zeilen für die neue ausgewählte Element (die ein völlig anderes Detail haben Anzeige von dem zuvor ausgewählten Elemente). Dies funktioniert gut für eine Weile. Aber wenn ich immer von einem ausgewählten Element zum anderen für eine recht lange Zeit zu bewegen, werden die Auffrischungen sehr langsam (3-5 Sekunden). Das macht es klingen wie ich bin nicht alles richtig entsorgen, aber ich kann nicht herausfinden, was ich fehle. Hier ist mein Code zum Löschen des Table:

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

Und wenn ich fertig Laden bis alle Steuerelemente erhalten möchte ich in den Table für die nächste Detailanzeige hier nenne ich:

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

Ich bin mit nichts aber Etikett (und einen Text sehr selten) innerhalb des Table, und ich füge hinzu, die Labels und Textfelder auf die Steuerungsliste (in DisposeAndClearControls verwiesen ()), wenn ich sie erstellen. Ich habe gerade versucht, über detailTable.Controls iterieren und sich auf diese Weise entsorgen, aber es schien die Hälfte der Kontrollen (durch Schreiten durch sie im Debugger bestimmt) zu verpassen. Auf diese Weise Ich weiß, ich sie alle.

ich in allen möglichen Vorschlägen interessiert sein würde zur Verbesserung der Leistung zeichnen, sondern vor allem, was verursacht den Abbau über mehrere Auswahlmöglichkeiten.

War es hilfreich?

Lösung 3

Ich habe die haltige Form nur eine neue Version meiner Benutzerkontrolle auf jeder Auswahländerung zu konstruieren. Es verfügt die alten und baut einen neuen. Das scheint ganz gut zu erfüllen. Ich hatte ursprünglich ohnehin mit Wiederverwendung von nur einem aus Performance-Gründen gegangen. Klar, dass nicht die Leistung verbessern. Und die Leistung ist kein Problem, wenn ich die alten entsorgen und einen neuen erstellen.

Bedauerlich, dass die Table Lecks so, though.

Andere Tipps

Nur ein benutzerdefiniertes Steuerelement verwenden, die von Table erbt und stellen Sie die Eigenschaft DoubleBuffered auf wahr, funktioniert super ... vor allem, wenn Sie dynamisch hinzufügen oder Zeilen entfernen.

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

Ich hatte ein ähnliches Problem mit Tablelayout. Wenn ich verwenden TableLayout.Controls.Clear () Methode steuert das Kind wird nie entsorgt, aber wenn ich einfach das Tablelayout fällt gelassen, ohne sie zu löschen, stoppte das Leck. Im Nachhinein ist es komisch ich die Clear-Methode zu verwendet verhindern eine Art Leck.

Offenbar hat Clear-Methode nicht explizit die Kontrollen verfügt (was Sinn macht, denn die Tatsache, dass man sich aus dem Tablelayout entfernt, heißt das nicht, dass Sie mit ihnen fertig sind) und aus dem Tablelayout der untergeordneten Steuerelemente Entfernen verhindert, dass die Bereinigungsroutine zu entsorgen die Kinder, wenn die LayoutTable selbst angeordnet wird (es weiß einfach nicht über sie mehr).

Meine Empfehlung: Löschen Sie die detailTable.Controls.Clear (); Linie, entfernen Sie die detailTable selbst von der übergeordneten Kontrollen Sammlung und entsorgen, dann erstellen Sie eine brandneue Tablelayout für die nächste Runde. verliert auch die DisposeAndClearControls Methode vollständig, da Sie es nicht benötigen. Nach meiner Erfahrung, es funktionierte gut.

Auf diese Weise werden Sie nicht Ihre gesamte Benutzerkontrolle mehr haben zu recyceln, sondern nur das Tablelayout innerhalb.

stand ich das gleiche Problem und eine gute Möglichkeit gefunden, ohne zu viel zu ändern:

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

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

Leider ist der einzige Rat, den ich anbieten kann, ist Pflege der Platzierung Ihrer Kontrollen zu nehmen, um sich. In meiner Erfahrung ist das .NET-Table während sehr nützlich, ist etwas undicht und wird unusably langsam, wie es wächst (und es dauert nicht eine unzumutbare Anzahl der Zellen zu diesem Punkt zu gelangen, entweder). Dieses Verhalten kann auch im Designer zu sehen.

TableLayoutPanel.Controls.Clear () funktioniert gut für mich, vielleicht ist es, weil ich klar es von einem anderen Register als sein angezeigt in.

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

foreach (Control control in controls)
{
    control.Dispose();
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top