Settare il DefaultButton sulle pagine ASP.NET in presenza di MasterPage

Giorgio Borelli

Impostare il focus ed il bottone (submit) di default all'interno di una pagina aspx, per scatenare l'evento OnClick direttamente premendo il tasto invioIn ASP.NET le pagine aspx sono basate su un unico form (con l'attributo runat="server"), all'interno della pagina il defaultfocus ed il defaultbutton vengono impostati sui primi controlli letti nel codice della pagina, si può variare questo comportamento di default specificando diversamente grazie alle proprietà "defaultfocus" e "defaultbutton" del main form, a dette proprietà assegniamo l'ID di un controllo TextBox e di un Button, in modo che la prima Text attiva sulla quale scrivere ed il primo bottone attivo al quale corrisponderà un click (causando un PostBack) alla pressione del tasto invio (Enter) saranno quelle da noi specificate. Identico risultato si può ottenere nel codebehind specificando sempre l'ID del controllo in questo modo Page.Form.DefaultFocus = "ClientIdControl"; e Page.Form.DefaultButton = "ClientIdControl";.

Fin qui davvero tutto molto semplice, le cose si complicano un pò in presenza di una MasterPage o di un controllo Login, peggio ancora se abbiamo la combinazione delle due cose. Con una MasterPage il problema si pone in quanto specificando la proprietà defaultbutton nella sua form, l'ID del controllo client non viene riconosciuto se si trova all'interno di una pagina aspx per la quale è stata specificata la suddetta MasterPage. Nel caso di un controllo login il problema è analogo, l'ID del controllo button non viene riconosciuto in quanto annidato all'interno del controllo Login di asp.net. Come fare allora per specificare un defaultbutton che reagisca direttamente alla pressione del tasto Invio in questi casi? La soluzione esiste, e possono essere anche più di una, basterà scrivere poche righe di codice aggiuntivo o usare dei piccoli trucchetti, vediamo come fare.

Specificare il DefaultButton in Caso di MasterPage 

In presenza di una MasterPage, assegnando alla proprietà "DefaultButton" del form, l'ID di un controllo interno alla pagina per la quale è stata specificata la MasterPage, questo non verrà riconosciuto e fornirà al caricamento della pagina il seguente messaggio d'errore (eccezione):

Exception Details: System.InvalidOperationException: The DefaultButton of 'form1' must be the ID of a control of type IButtonControl.

Questo errore è causato dal fatto che il controllo si trova all'interno della pagina "figlia" della MasterPage per la quale è stato specificato un "ContentPlaceHolder", questo fa sì che al nome del controllo venga aggiunto in fase di output della pagina html dei caratteri che identificano il PlaceHolder, provando infatti a visualizzare il codice html generato, se per ID avevamo specificato "DefaultButton", ci ritroveremo nel name del controllo qualcosa tipo "ctl00$ContentPlaceHolder1$ButtonDefault", come si vede viene aggiunto il nome del PlaceHolder più altri caratteri tra cui anche il simbolo del dollaro. Un primo e rudimentale metodo per ovviare a questo problema, è quello di copiare il nome del controllo così per come viene generato nel codice html ed assegnarlo alla proprietà DefaultButton. Questa soluzione funziona, ma di certo è poco elegante, e soprattutto poco flessibile, basta infatti cambiare anche una sola lettera del nome assegnato al controllo per ritrovarsi nuovamente con la stessa eccezione specificata pocanzi.

Una soluzione molto più robusta ed elegante è assegnare invece alla proprietà defaultbutton della pagina lo "UniqeID" del button server control, direttamente nel code behind della pagina aspx all'interno dell'evento Load, in questo modo:

protected void Page_Load(object sender, EventArgs e)
{
    Page.Form.DefaultButton = ButtonDefault.UniqueID;
}

specificando la proprietà "UniqueID" si assegna alla proprietà DefaultButton del form della pagina la stringa dell'ID che gerarchicamente qualifica ed identifica in maniera univoca il server control. Questo approccio non solo è più elegante e robusto, ma risolve allo stesso tempo anche la seccatura di un eventuale cambio di nome (la stringa) nell'ID specificato per il controllo. Così facendo otteremo il risultato che alla pressione del tasto Invio o Enter il bottone da noi specificato come di default risulterà quello attivo, scatenando un PostBack che possiamo gestire come crediamo all'interno dell'Handler dell'evento OnClick.

NOTA: una proprietà dei server control molto simile a "UniqueID" è "ClientID", quest'ultima preleva l'ID generato da ASP.NET ed assegnato al controllo quando la pagina viene restituita al client. La differenza tra UniqueID e ClientID risiede nel fatto che la prima consente di prelevare il name univoco assegnato al controllo mentre il secondo preleva l'ID, nel nostro caso  risulta pertanto più potente lo UniqueID. Assegnate sia il Client che lo Unique ID e poi visualizzate il codice della pagina html generato, vi renderete conto della differenza delle due proprietà.

Abbiamo già visto due metodi per assegnare il defaultbutton in pagine ASP.NET basate su MasterPage, con quest'ultimo approccio siamo intervenuti direttamente sulla pagina aspx e non sulla Master, possiamo agire anche sulla MasterPage ed ottenere lo stesso risultato, bastano queste poche righe di codice:

Button btnDefault = (Button)ContentPlaceHolder1.FindControl("ButtonDefault");

        if (btnDefault != null)
            form1.DefaultButton = btnDefault.UniqueID;

come vedete per prelevare il button control presente nel ContentPlaceHolder della pagina dove è definito, abbiamo usato il metodo FindControl, per il quale specifichiamo l'ID del controllo e ne facciamo il cast per ottenere direttamente un button control e non un controllo generico. Infine assegniamo il defaultbutton con la proprietà UniqueID come fatto in precedenza.

Anche con questo terzo ed ultimo approccio lo scopo è quello di specificare l'ID univoco del button control per il quale desideriamo risulti attivo e scateni un postback alla pressione del tasto Invio, però a differenza del secondo abbiamo un ulteriore vantaggio in quanto è centralizzato nella MasterPage ed opportunamente modificato può essere sfruttato a livello globale da tutte le pagine basate su questa MasterPage, evitando in un colpo solo la inutile duplicazione di codice su svariate pagine ed una migliore manutenzione del codice, basta infatti intervenire in un solo punto (il codice della MasterPage) per ottenere che le modifiche si propaghino su tutte le pagine. Ad esempio, si potrebbe implementare un metodo pubblico che ricevi in ingresso lo UniqueID del submit control da settare come defaultbutton permettendo di differenziarlo a seconda delle pagine visualizzate.

NOTA: la funzione FindControl di ASP.NET è sorprendentemente potente, presente nella stragrande maggioranza dei controlli genitori di ASP.NET consente con estrema facilità di recuperare un controllo annidato e gestirne i contenuti e le proprietà, passatemi il termine, come se fosse direttamente a portata di mano. Un altro bell'esempio dell'uso della funzione FindControl è stato visto nell'articolo: "Intercettare un controllo all'interno della riga di una GridView".

 

Conclusioni

Le proprietà DefaultButton e DefaultFocus sono state introdotte a partire dalla versione di ASP.NET 2.0, prima in ASP.NET 1.1 lo stesso risultato si poteva ottenere, in maniera molto più macchinosa agendo via Javascript. Tutto quello sin qui detto sul DefaultButton può essere utilizzato con le dovute modifiche anche al concetto di Focus e DefaultFocus per le TextBox. La comodità di poter impostare le Text ed i Button di default non è roba da poco, l'orientamento del web di rendere sempre più facile e piacevole la navigazione delle pagine web si vede anche da queste accortezze, è comodo ad esempio consentire all'utente di poter accedere direttamente al login alla pressione del tasto Invio senza bisogno di spostarsi sul bottone accedi col mouse, o ancora rendere immediatamente attiva al caricamento della pagina la prima casella di testo nella compilazione di un form, sono dettagli che fanno bene al sito ed anche e soprattutto a chi lo naviga, e come visto il modo corretto per farlo è quello di assegnare lo UniqueID del controllo server.

Ci sono casi per i quali gli approcci sin qui descritti non sono sufficienti, ad esempio nel caso di MasterPage annidate o di controlli interni ad altri controlli, quali Panel e Login, tuttavia la tecnica è pressochè la stessa, basterà adattarla all'esigenza della pagina web sviluppata e dei controlli in essa presenti. Vista comunque l'ampiezza dell'argomento, desidero approfondirlo con un ulteriore articolo, che tratterà l'Impostazione del DefaultButton in presenza del controllo Login di ASP.NET.

 

Chiunque voglia aggiungere qualcosa o chiedere ulteriori chiarimenti su Impostare il DefaultButton in presenza di MasterPage può farlo liberamente tramite i commenti, ogni vostro contributo alla discussione sarà ben accetto.

Categorie: ASP.NET

Tags:

Pingbacks and trackbacks (1)+

Aggiungi Commento

biuquote
Loading