posts - 644, comments - 2003, trackbacks - 137

My Links

News

Raffaele Rialdi website

Su questo sito si trovano i miei articoli, esempi, snippet, tools, etc.

Archives

Post Categories

Image Galleries

Blogs

Links

[ASP.NET] Un custom control per dare il focus lato client

Avete presente quando caricate la pagina di google quanto sia comodo avere subito il focus sulla textbox di ricerca?
Lo script da usare è estremamente semplice:

dove IdControlloLatoClient è l'id del controllo a cui dare il focus, tassativamente ottenuto con la proprietà ClientID.
Lo script va poi registrato con il metodo RegisterStartupScript.

Per risolvere la questione in modo più elegante ho buttato giù un piccolo custom control che registra questo script.

[DefaultProperty("FocusControl"), ToolboxData("<{0}:FirstFocus runat=server>")]
public class FirstFocus : Control
{
   private string StartScript = "\r\n ";
   protected Control FindNestedControl(Control root, string name)
   {
      foreach(Control ctl in root.Controls)
      {
      if(ctl.ID == name)
         return ctl;
      if(ctl.HasControls())
         return FindNestedControl(ctl, name);
      }
      return null;
   }

   protected
string GetControlRenderID(string name)
   {
      //Control ctl = FindControl(name);
      Control ctl = FindNestedControl(Page, name);
      if (ctl == null)
         return "";
      return ctl.ClientID;
   }
  
   protected
override void OnPreRender(EventArgs e)
   {
      if(FocusControl == string.Empty)
         return;
      string CID = GetControlRenderID(FocusControl);
      if(CID != string.Empty)
         Page.RegisterStartupScript(ClientID, StartScript + "document.all['" + CID + "'].focus();" + EndScript);
   }

   ///


   /// Il control ID da specificare nel caso degli UserControl è quello dello UserControl
   /// Poi è necessario che lo UserControl faccia l'override della proprietà ClientID
   /// e restituisca al posto del proprio quello del controllo che si vuole guadagni il focus
   ///

   [Category("Behaviour"),
   DefaultValue(""),
   Description("Control you wish will gain control at load time"),
   TypeConverter(
typeof(AllPageControlsConverter))]
   public string FocusControl
   {
      get 
      {
         string ctl = ViewState["FocusControl"] as string;
         return (ctl == null) ? string.Empty : ctl;
      }
      set 
      {
         ViewState["FocusControl"] =
value;
      }
   }
}

Per rendere più gradevole l'uso del controllo ho poi costruito un UITypeConverter per scegliere a design time, con una combo nella property toolbox, il controllo a cui dare il focus.

public class AllPageControlsConverter : StringConverter
{
   private object[] GetControls(ITypeDescriptorContext context)
   {
      IContainer container = context.Container;
      ComponentCollection coll = container.Components;
      ArrayList list =
new ArrayList();
      foreach (IComponent comp in coll)
      {
         if (!(comp is Control))
            continue;

         Control ctl = (Control) comp;
         if ((ctl.ID != null) && (ctl.ID.Length != 0) && (ctl.ID != (((Control)context.Instance)).ID))
         {
            list.Add(
string.Copy(ctl.ID));
         }
      }
      list.Sort(Comparer.Default);
      return list.ToArray();
   }

   public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
   {
      if (context == null || context.Container == null)
         return null;
      
object[] ctls = GetControls(context);
      if (ctls != null)
         return new TypeConverter.StandardValuesCollection(ctls);
      return null;
   }

   public
override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
   {
      return false;
   }
   public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
   {
      return true;
   }
}

Infine un ultimo particolare: e se il controllo a cui dare il focus è contenuto all'interno di uno UserControl? La risposta è semplice, basta fare l'override nello user control della proprietà ClientID e restituire quello del controllo 'principale'. In questo modo, indicando lo user control come destinatario del focus, verrà letto il ClientID del controllo contenuto nello User Control.

/// proprietà ClientID dello User Control
public override string ClientID
{
   get
   {
      return txtUsername.ClientID;   // txtUsername è il controllo contenuto nello User COntrol a cui si vuole dare il focus
   }
}

Ci sono sicuramente degli spunti di miglioramento, come il piccolo spreco nel viewstate per conservare il nome del controllo. Ma a me è bastato così ...

Print | posted on mercoledì 22 settembre 2004 00:35 | Filed Under [ ASP.NET [Italiano] ]

Feedback

Gravatar

# re: [ASP.NET] Un custom control per dare il focus lato client

Ciao Lawrence,
per prima cosa ti rimane il problema del ClientID e quindi le due righe che tu hai scritto devono necessariamente essere create dal lato server altrimenti rischi di mettere l'id sbagliato (soprattutto usando UserControl e template).
Inoltre aggiungendo l'attributo sul body avrei dovuto realizzare un controllo da sostituire al body e questo può dare più grane dei benefici.

Il vantaggio del design time non lo vedo solo in termini di comodità ma anche di maggiore manutenzione e pulizia della pagina.
22/09/2004 01:21 | Raffaele Rialdi
Gravatar

# re: [ASP.NET] Un custom control per dare il focus lato client

Ok grazie della spiegazione :)
22/09/2004 01:49 | Lawrence Oluyede
Gravatar

# re: [ASP.NET] Un custom control per dare il focus lato client

Ciao Fabio
Quello che vuoi fare è molto semplice, forse ti manca qualche base.

Ti consiglio di iscriverti alle community/usergroups ai quali porre le domande e da cui ricevere (anche da me) le risposte. In questo modo le risposte rimangono pubbliche e consultabili via google groups o i forum degli user groups.

Con Outlook express puoi collegarti a news.microsoft.com via NNTP.
Il newsgroup di asp.net è microsoft.public.it.dotnet.asp
Oppure www.ugidotnet.org con i suoi forum
O ancora www.aspitalia.com con i suoi forum.

Ciao e in bocca al lupo.
02/04/2008 15:10 | Raffaele Rialdi
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET