Monday, December 24, 2007

ListItemCollection e gli Attributes

. Monday, December 24, 2007

I controlli in ASP.NET come per esempio DropDownList, RadioButtonList, ListBox e CheckBoxList ereditano da System.Web.UI.WebControls.ListControl, quindi espongono il contenuto attraverso una collection Items.
In generale se si vuole modificare lo stile dei vari item si fa uso della collection Attributes, peccato che in ASP.NET 1.1 tali attributi non vengano renderizzati, si tratta di un bug.
Ovviamente in ASP.NET 2.0 tale problema non si "manifesta" (è fondamentale sottolineare come sia necessario eseguire l'add ad ogni postback, questo perchè sia in Asp.Net 1.x che in 2.0 la collezione degli attributes dei ListItem contenuti nel controllo non vengono salvati nel ViewState), infatti se per esempio vogliamo modificare l'attributo background dei singoli elementi che compongono il controllo RadioButtonList(rbList) basta valorizzare la chiave style nel seguente modo:

   1: rbList.Items[0].Attributes.Add("style", "background-color:red");
   2: rbList.Items[1].Attributes.Add("style", "background-color:DeepPink");


Se vogliamo ottenere lo stesso risultato anche in ASP.NET 1.1?
Nel caso specifico una possibile soluzione è quella di creare il proprio controllo ereditando da RadioButtonList ed effetturare l'override del metodo Render:


   1: public class RadioButtonListPlus : RadioButtonList
   2: {
   3:   protected override void Render(HtmlTextWriter writer)
   4:   {
   5:     ListItemCollection items = this.Items;
   6:     if (items.Count > 0)
   7:     {
   8:       for (int i=0; i<items.Count; i++)
   9:       {
  10:         ListItem item = items[i];
  11:         //Creazione del tag span
  12:         writer.WriteBeginTag("span");
  13:         AttributeCollection attrs = item.Attributes;
  14:         foreach (string key in attrs.Keys)
  15:           //Add dello stile
  16:           writer.WriteAttribute( key, attrs[key]);
  17:         writer.Write( ">");
  18:         //Creazione del controllo radio
  19:         writer.WriteBeginTag("input");
  20:         writer.WriteAttribute( "id", this.ClientID + "_" + i.ToString());
  21:         writer.WriteAttribute("type", "radio");
  22:         writer.WriteAttribute("name", this.UniqueID);
  23:         writer.WriteAttribute("value", item.Value);
  24:         if( item.Selected)
  25:           writer.WriteAttribute("checked", "checked");
  26:         if( this.AutoPostBack)
  27:         {
  28:           RadioButton rb = new RadioButton();
  29:           rb.ID = this.ClientID + "_" + i.ToString();
  30:           writer.WriteAttribute( "onclick", Page.GetPostBackClientEvent( rb, string.Empty));
  31:         }
  32:         writer.Write( ">");
  33:         //Creazione del controllo label contenente il testo da visualizzare accanto al RadioButton
  34:         if( item.Text.Length > 0)
  35:         {
  36:           writer.Write( "<label");
  37:           writer.WriteAttribute( "for", this.ClientID + "_" + i.ToString());
  38:           writer.Write( ">");
  39:           writer.Write( item.Text);
  40:           writer.WriteEndTag( "label");
  41:         }
  42:         writer.WriteEndTag("input");
  43:         writer.WriteEndTag("span");
  44:       }
  45:     }
  46:   }
  47: }


In sostanza nel metodo Render vado a creare e manipolare l'HTML del controllo RadioButtonList, in modo da aggiungere un tag span, che fa da contenitore al controllo RadioButton e al controllo Label.
Infine nella nostra pagina aspx è necessario registrare il nuovo controllo:


   1: <%@ Register TagPrefix="cc1" Namespace="namespace" Assembly="assembly" %>

ed inserirlo nel form:


   1: <cc1:RadioButtonListPlus runat="server" id="rbListPlus">
   2:   <asp:ListItem Value="1" Selected="True">test1</asp:ListItem>
   3:   <asp:ListItem Value="2">test2</asp:ListItem>
   4: </cc1:RadioButtonListPlus>

Per chi è interessato trova un'ulteriore soluzione in questo interessante articolo in lingua inglese.

0 commenti:

Post a Comment