Settare il DefaultButton in presenza del Login Control

Giorgio Borelli

Effettuare il submit del controllo login direttamente alla pressione del tasto invio in ASP.NETCome visto nell'articolo precedente, a partire da ASP.NET 2.0 è possibile impostare il DefaultButton ed il DefaultFocus di una pagina aspx, anche in presenza di MasterPage.

Il concetto e le problematiche di questo argomento si estendono anche in presenza di controlli genitori, primo fra tutti il controllo Login di ASP.NET, essendo infatti il bottone di Login interno al controllo (più precisamente nell'AnonymousTemplate), la stringa identificativa dell'ID del bottone "Accedi" viene modificata dal parser di ASP.NET al momento del rendering della pagina, creando di fatto un'eccezione durante la compilazione, poichè la proprietà DefaultButton si aspetta un ID di un controllo che erediti direttamente da IButtonControl, e non riconoscendolo genera l'eccezione.

Così come spiegato in presenza di MasterPage, anche per il controllo Login è possibile implementare più di una soluzione per far sì che il submit del login avvenga direttamente alla pressione del tasto Invio (Enter), andiamo a scoprire come fare.

Impostare il DefaultButton del controllo Login via codebehind

Per consentire il submit del controllo Login alla pressione del tasto Invio all'interno di una pagina aspx, per la quale sia stata definita anche una MasterPage, basta aggiungere questa riga di codice nel codebehind:

protected void Page_Init(object sender, EventArgs e)
{
       Page.Form.DefaultButton = LoginView1.FindControl("LoginButton").UniqueID;
} 

ancora una volta ci viene in aiuto il metodo FindControl presente ovviamente anche nel Login Control. Una volta recuperato il ButtonControl, ne assegniamo lo UniqueID alla proprietà DefaultButton della Pagina (si poteva specificare anche this, piuttosto che Page).

Questa tecnica funziona perfettamente anche se per la pagina aspx è stata specificata una MasterPage.

Desidero porre l'attenzione sul fatto che questa assegnazione sia stata specificata nell'evento Page_Init e non nel Page_Load, Init è il primo è vero evento durante l'inizializzazione della pagina, mentre il Load si verifica successivamente al caricamento della pagina richiesta. Qualcuno potrebbe obbiettare che inserire l'assegnazione del DefaultButton nell'evento Init potrebbe non far funzionare il submit alla pressione del tasto Invio, poichè il Login Control non è ancora caricato nella pagina. Questo è vero ma non costituisce un problema, le pagine aspx propagano i propri eventi anche ai server control in essa contenuti, sempre secondo la gerarchia di annidamento con cui sono definiti, quindi anche il Login Control verrà inizializzato così come avviene per la pagina che lo contiene. In conclusione, a livello di funzionamento è indifferente assegnare il DefaultButton nell'evento Init anzichè nel Load, ma credo sia più giusto inserirlo durante l'inizializzazione della pagina (e conseguentemente del controllo Login). Se qualcuno volesse aggiungere qualcosa in proposito, lo spazio dei commenti è a vostra disposizione.

 

Impostare il DefaultButton del controllo Login tramite il controllo Panel

Come più volte accennato, la pagina aspx è un container, all'interno del quale vengono definiti ASP.NET ed HTML control, alcuni di questi sono a loro volta dei contenitori di altri oggetti. Secondo questa logica è pertanto possibile definire più di un DefaultButton all'interno di una pagina aspx; ed è proprio basandosi su questo concetto che spiegheremo come settare un DefaultButton per un controllo Login che risulti attivo alla pressione del tasto Invio.

Possiamo definire il DefaultButton non solo per il Form del Page, ma anche per ogni singolo Panel presente nella pagina, ogni DefaultButton prevarrà sugli altri quando il Panel che lo contiene risulterà attivo (si starà operando al suo interno). Per il controllo Login basterà inserire un Panel Control subito dopo l' AnonymousTemplate. Il Login Control si troverà così dentro il Panel, per il quale specifichiamo il DefaultButton nell'omonima proprietà, in questo modo:

  <asp:LoginView ID="LoginView1" runat="server">

                <LoggedInTemplate>

                        <asp:LoginName ID="LoginName" runat="server" />

                        <asp:LoginStatus ID="LoginStatus" runat="server" />

                </LoggedInTemplate>

                <AnonymousTemplate>

                    <asp:Panel ID="panelLogin" runat="server" DefaultButton="Login$LoginButton">

                        <asp:Login ID="Login" runat="server" />

                    </asp:Panel>

                </AnonymousTemplate>

            </asp:LoginView>

non abbiamo fatto altro che specificare nella proprietà DefaultButton del Panel, la stringa identificativa del LoginButton, ed anche questo secondo metodo funziona bene in presenza di MasterPage, basta che il Panel risulti attivo, e siccome stiamo proprio operando all'interno del Panel quando scriviamo i nostri dati per il Login, alla pressione del tasto Invio, il Login Button scatenerà il submit.

 

Conclusioni

Il primo metodo è sicuramente da preferire, è più elegante e poi specifichiamo lo UniqueID, questo evita problematiche inerenti l'identificativo del controllo sia in caso che venga cambiata la stringa dell'ID nel markup della pagina, sia in presenza di uno o più annidamenti in controlli genitori. Ciò nonostante se abbiamo un solo Panel a livello di pagina anche il secondo metodo funziona bene, e la sua implementazione è davvero semplice ed immediata.

Per chi volesse approfondire il discorso sul DefaultButton (ed anche DefaultFocus), può leggere l'articolo precedente: Settare il DefaultButton in presenza di MasterPage.

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

Categorie: ASP.NET

Tags:

Commenti (6) -

ciao, io sono riuscito così:

Login log = (Login)LoginView1.FindControl("Login1");
Button bt = (Button)log.FindControl("LoginButton");
Page.Form.DefaultButton = bt.UniqueID;

altrimenti mi dava errore..

Rispondi

Ciao Claudio,
sicuro che il tuo controllo Login non sia a sua volta contenuto in qualche altro controllo contenitore, come il Panel o più semplicemente dentro un tag div?
In tal caso l'identificativo del LoginButton cambia, il FindControl non lo trova restituendoti un oggetto null e quindi ti dà un errore (eccezione) nell'assegnamento dello UniqueID.

Tuttavia, il tuo metodo non fà una piega, e sostanzialmente fai la stessa cosa, solo che prima trovi il controllo Login (contenuto nel LoginView) e poi il LoginButton (contenuto nel Login) ed infine assegni lo UniqueID del button al DefaultButton della pagina, va benissimo, c'è solo una riga di codice in più che non penso possa portare chissà che decadimento di prestazioni in una pagina di Login.

Comunque, e questo vale anche per il mio esempio, sarebbe bene mettere un controllo prima di fare l'assegnazione, di questo tipo:

Login log = (Login)LoginView1.FindControl("Login1");
if(log != null)
{
Button bt = (Button)log.FindControl("LoginButton");
if(bt != null)
   Page.Form.DefaultButton = bt.UniqueID;
}

proprio per evitare eccezioni su eventuali oggetti null. Ricorda, l'eccezioni è meglio evitarle, gestirle comporta uno spreco di risorse di gran lunga maggiore.

Rispondi

però grazie per l'articolo, è stato il passaggio fondamentale per una soluzione a lungo agognata ma non trovata!

Rispondi

Prego, cerchiamo di darci da fare, probabilmente è stato l'illustrazione del metodo FindControl e l'uso della proprietà UniqueID il punto di svolta.

Ad ogni modo felice di esserti stato utile;

Rispondi

e catturo l'eccezione: Object reference not set to an instance of an object.
che esce quando una volta loggato torno sulla pagina del login..
non è molto elegante ma funziona e se qualcuno la può migliorare ed ha voglia di spiegarmi i motivi per cui a me funziona solo in questo modo(credo che in parte sia perché non ho l'accesso diretto al login1), ben venga!

Rispondi

Il messaggio dell'eccezione parla chiaro "il riferimento all'istanza dell'oggetto è nullo".

Quando sei loggato il controllo LoginView non ti mostra più l'AnonymousTemplate (e quindi il controllo login) bensì il LoggedInTemplate, se non fai alcun controllo a monte ed al page load si ritrova questo codice:
Login log = (Login)LoginView1.FindControl("Login1");

ovviamente l'oggetto restituito dal FindControl è nullo ed alla successiva riga di codice quando usi l'oggetto log si scatena l'eccezione.
Va bene, che la catturi e la gestisci, però come detto prima meglio evitare lo scatenarsi delle eccezioni piuttosto che gestirle dopo.

Attenzione la mia ipotesi è solo buttata lì al volo, non l'ho provata e non ho visto il tuo codice, nè il markup nè il codebehind, quindi può essere che mi sbaglio, non sò di preciso quale oggetto sia nullo, può essere anche un'altra cosa, tuttavia mettere un controllo e provare di sicuro male non farà.

Magari fammi sapere come và, grazie dell'intervento, saluti Giorgio.

Rispondi

Pingbacks and trackbacks (1)+

Aggiungi Commento

biuquote
Loading