Roberto Brunetti

ASP.NET - Mobility
Team System

SharePoint Conference

.NET Programming

Corsi

SharePoint

BeginUpdate - SuspendLayout

Sui device basati su Windows Ce il disegno dei bit (pixel) sullo schermo non è velocissimo: mancano le schede grafiche a cui siamo abituati sui desktop. Tutte le volte che occorre eseguire più operazioni che modifichino un controllo sullo schermo conviene quindi adottare alcune tecniche per evitare il "repaint" ad ogni modifica. Queste tecniche sono valide anche sul Desktop dove comunque, per il motivo indicato, si soffre molto meno.

Ad esempio:
1) Riempire un controllo con una serie di dati (Add su una ListBox)
2) Spostare e modificare la dimensione di un controllo nello stesso tempo
3) Eseguire il binding di dati con BindingSource o tramite DataSource

Alcuni controlli espongono i metodi BeginUpdate e EndUpdate che consentono di prevenire il repainting (in generale il disegno) del controllo durante l'aggiunta di dati. I controlli che supportano tali metodi sono ListBox, ComboBox, ListView, TreeView. Visto il .NET CF non dispone del metodo AddRange, utilizzato sul desktop per aggiungere una serie di elementi ai controlli, è bene utilizzare questi metodi per sospendere il disegno durante il popolamento di dati. Anche DataGridColumnStyle supporta tali metodi. Un vecchio trucco ancora valido per i controlli che non supportano tali metodi, è quello di impostare il controllo invisibile (Visible=false), popolarlo di dati e poi riportarlo Visible=true.

Non ci credete che si va più forte ? Provate. Ero da un cliente settimana scorsa in cui una query di rimpimento di una griglia impiegava 24 secondi circa...bene, è bastato un Visible=false/Visible=true sull'intero controllo DataGridView per passare a ....4 secondi. In pratica si evita che il controllo si disegni per l'aggiunta di ogni record/campo, comprese le toolbar di scorrimento orizzontale e verticale che ad ogni record devono essere ricalcolate e disegnate.

I metodi SuspendLayout consente invece di sospendere la logica di layout consentendo di modificare più attributi (che ne modificano la visualizzazione) con performance maggiori. Ad esempio se dobbiamo spostare e allargare un controllo sul form conviene sospendere il layouting, impostare le varie proprietà (Location, Size, Dock, Anchor, ecc) e poi riabilitare il tutto. Conviene usare questa tecnica anche per aggiungere una serie di controlli su un controllo container. Ad esempio per aggiungere dinamicamente da codice una serie di controlli a un Form, a un Panel o a un TabControl conviene sospendere il layout dal container, aggiungere i controlli e riabilitare il layout (es. Form.ResumeLayout).
Questa tecnica viene usata anche da Visual Studio 2003 e 2005 nella sezione "region Windows Form Designer generated code" che vi riporto (un po' tagliata e con qualche commento in rosso per chiarezza) da una mia applicazione reale.


        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.mainMenu = new System.Windows.Forms.MainMenu();
            this.cmdAllBaseTableCursor = new System.Windows.Forms.Button();
            this.cmdAllSelectFieldsRSPrepared = new System.Windows.Forms.Button();
            this.cmdAllSelectFieldsDRPrepared = new System.Windows.Forms.Button();
            this.cmdAllSelectFieldsRS = new System.Windows.Forms.Button();
            this.cmdAllSelectFieldDataReader = new System.Windows.Forms.Button();
            this.cmdAllSelectFieldsDT = new System.Windows.Forms.Button();
            this.cmdAllSelectFieldsDS = new System.Windows.Forms.Button();
 
            ...Altri Controlli ...

            // Come si nota VS sospende il layout per tutti i container definiti
            this.tabDALNoDAL.SuspendLayout();
            this.tabAll.SuspendLayout();
            this.tabRange.SuspendLayout();
            this.tabSingle.SuspendLayout();
            this.SuspendLayout();
            //
            // tabDALNoDAL
            //
            this.tabDALNoDAL.Controls.Add(this.cmdFillPrepared);
            this.tabDALNoDAL.Controls.Add(this.txtQuanti);
            this.tabDALNoDAL.Controls.Add(this.cmdFill);
            this.tabDALNoDAL.Location = new System.Drawing.Point(0, 0);
            this.tabDALNoDAL.Name = "tabDALNoDAL";
            this.tabDALNoDAL.Size = new System.Drawing.Size(240, 190);
            this.tabDALNoDAL.Text = "Fill";
            //
 
            //
            this.tabAll.Controls.Add(this.cmdAllBiz);
            this.tabAll.Controls.Add(this.cmdAllBaseTableCursor);
            this.tabAll.Controls.Add(this.cmdAllSelectFieldsRSPrepared);
            this.tabAll.Controls.Add(this.cmdAllSelectFieldsDRPrepared);
            this.tabAll.Controls.Add(this.cmdAllSelectFieldsRS);
            this.tabAll.Controls.Add(this.cmdAllSelectFieldDataReader);
            this.tabAll.Controls.Add(this.cmdAllSelectFieldsDT);
            this.tabAll.Controls.Add(this.cmdAllSelectFieldsDS);
            this.tabAll.Controls.Add(this.cmdAllSelectStarDS);
            this.tabAll.Location = new System.Drawing.Point(0, 0);
            this.tabAll.Name = "tabAll";
            this.tabAll.Size = new System.Drawing.Size(232, 187);
            this.tabAll.Text = "All";


     ... Altri controlli...

     // Parte Finale
            this.MinimizeBox = false;
            this.Name = "frmMain";
            this.Text = "Form1";
            this.tabControl1.ResumeLayout(false);
            this.tabDALNoDAL.ResumeLayout(false);
            this.tabAll.ResumeLayout(false);
            this.tabRange.ResumeLayout(false);
            this.tabSingle.ResumeLayout(false);
            this.ResumeLayout(false);

        }

        #endregion


Come si nota nel codice vengono creati i controlli container, viene sospeso il layout, aggiunti i controlli e poi riabilitato (riesumato :-)) il layout.

Vedremo queste tecniche anche alla prossima FWC del 4 maggio mettendo in mezzo anche un po' di multithreading per completare il panorama.

Posted: apr 27 2006, 07.42 by rob | with no comments
Filed under: ,