Domanda

Ho un controllo utente che contiene un 2-colonna TableLayoutPanel e accetta comandi da aggiungere dinamicamente righe per visualizzare i dettagli di un elemento selezionato in un controllo separato. Quindi, l'utente seleziona una riga nella altro controllo (un DataGridView), e nel gestore di eventi SelectedItemChanged per DataGridView I deselezionare il controllo dettaglio e rigenerare tutte le righe per il nuovo elemento selezionato (che possono avere un dettaglio totalmente differente visualizzazione dalla voce selezionata in precedenza). Questa grande opera per un po '. Ma se continuo a spostarsi da un elemento selezionato ad un altro per un tempo abbastanza lungo, le rinfresca diventare molto lento (3-5 secondi ciascuno). Ciò rende il suono come non sto smaltire tutto correttamente, ma non riesco a capire cosa mi manca. Ecco il mio codice per cancellare la 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();
}

E una volta che ho finito di caricare il backup di tutti i comandi che voglio in TableLayoutPanel per la prossima visualizzazione dettaglio in questa sede è quello che io chiamo:

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

Non sto usando niente, ma le etichette (e un TextBox molto raramente) all'interno del TableLayoutPanel, e aggiungere le etichette e caselle di testo alla lista controlli (si fa riferimento in DisposeAndClearControls ()) quando creo loro. Ho provato appena l'iterazione di detailTable.Controls e lo smaltimento di loro in quel modo, ma sembrava di perdere la metà dei controlli (determinati facendo un passo attraverso di esso nel debugger). In questo modo so di farli tutti.

Sarei interessato a eventuali suggerimenti per migliorare le prestazioni di disegno, ma soprattutto cosa sta causando il degrado nel selezioni multiple.

È stato utile?

Soluzione 3

Ho cambiato il modulo contenente per costruire solo una nuova versione del mio controllo utente su ogni cambio di selezione. Dispone quello vecchio e costruisce uno nuovo. Questo sembra svolgere più che bene. Avevo originariamente andato con il riutilizzo di un solo per motivi di prestazioni in ogni caso. Chiaramente che non migliora le prestazioni. E la prestazione non è un problema se io dispongo quello vecchio e creare uno nuovo.

Peccato che le fughe di notizie TableLayoutPanel del genere, però.

Altri suggerimenti

utilizzare solo un controllo personalizzato che eredita da TableLayoutPanel e impostare la proprietà DoubleBuffered il vero, funziona alla grande ... soprattutto quando si aggiunge in modo dinamico o rimuovere righe.

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

Ho avuto un problema simile con TableLayout. Se ho usato TableLayout.Controls.Clear () il metodo, il bambino non ha mai avuto controlli smaltito ma quando ho semplicemente lasciato cadere la TableLayout senza cancellare esso, la perdita si fermò. Col senno di poi, è divertente ho usato il metodo Clear per prevenire qualche tipo di perdita.

A quanto pare, metodo Clear non esplicitamente smaltire i controlli (che ha un senso, perché il fatto che sono stati rimossi dalla TableLayout non significa che si è fatto con loro) e la rimozione dei controlli figlio dalla TableLayout impedisce alla routine di pulitura di disporre dei bambini quando la stessa viene smaltito LayoutTable (semplicemente non sa più di loro).

La mia raccomandazione: Eliminare la detailTable.Controls.Clear (); la linea, rimuovere il detailTable se stesso da Controlli dei genitori la raccolta e lo smaltimento di esso, quindi creare un nuovo marchio TableLayout per il prossimo turno. perdere anche il metodo DisposeAndClearControls del tutto dal momento che non sarà necessario. Nella mia esperienza, ha funzionato bene.

In questo modo, non si dovrà riciclare più il controllo utente intero ma solo la TableLayout all'interno.

Ho affrontato lo stesso problema ed ho trovato un buon modo senza cambiare troppo:

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)

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

Purtroppo, l'unico consiglio che posso offrire è di prendersi cura del posizionamento dei controlli da soli. Nella mia esperienza .NET TableLayoutPanel, mentre molto utile, si perde qualcosa e diventa unusably lento come cresce (e non ci vuole un numero ragionevole di cellule per arrivare a questo punto, o). Questo comportamento può essere visto nella finestra di progettazione pure.

TableLayoutPanel.Controls.Clear () funziona bene per me, forse è perché ho cancellarlo da una scheda diversa rispetto al suo visualizzato in.

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

foreach (Control control in controls)
{
    control.Dispose();
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top