2009-06-15 4 views
50

mi aspetterei questo:Perché ASP.Net RadioButton e CheckBox eseguono il rendering all'interno di Span?

<asp:CheckBox ID="CheckBox1" runat="server" CssClass="myClass" /> 
<asp:RadioButton ID="RadioButton1" runat="server" CssClass="myClass" /> 
<asp:TextBox  ID="TextBox1"  runat="server" CssClass="myClass" /> 

... per rendere in questo modo (con alcuni attributi asportate per chiarezza):

<input id="CheckBox1" type="checkbox" class="myClass" /> 
<input id="RadioButton1" type="radio" class="myClass" /> 
<input id="TextBox1"  type="text"  class="myClass" /> 

... quando in realtà, il RadioButton e CheckBox essere avvolto con un tag span e la classe CSS viene applicata lì.

<span class="myClass"><input id="CheckBox1" type="checkbox" /></span> 
<span class="myClass"><input id="RadioButton1" type="radio" /></span> 
<input type="text" id="TextBox1" class="myClass" /> 

C'è un motivo per questo ed esiste un modo per evitarlo? Rende selettori di jQuery brutto dal momento che non si può prendere tutti con:

$("input.myClass") 

Concesso è solo andare a:

$("input.myClass, span.myClass input") 

... ma questo è brutto. Potrei scrivere il mio selezionatore, ma di nuovo non è elegante come dovrebbe essere.

+0

come solo $ (". MyClass")? – Hardwareguy

+1

Non una risposta, ma solo commiserazione - quando ho iniziato a lavorare sulla piattaforma .NET alcuni anni fa e stavo usando JS per scoprire il valore di una casella di controllo, ho trascorso alcune ore cercando di capire perché i miei valori non erano avviso. Indovina cosa - i tag span. Mi sono sempre chiesto perché MS ha aggiunto tag ridondanti per i loro pulsanti radio e le caselle di controllo! – Dhana

+0

@Hardwareguy A volte quello sarà lo span ea volte quello sarà l'input. Quello è il problema. $ ("input.myclass") potrebbe essere un po 'troppo specifico, ma $ (". myClass") potrebbe darti lo stesso mal di testa. – Mark

risposta

42

I controlli Web nello spazio dei nomi System.Web.UI.WebControls possono essere visualizzati in modo diverso nei vari browser. Non puoi contare su di loro rendendo sempre gli stessi elementi. Possono aggiungere tutto ciò che pensano sia necessario per farlo funzionare nel browser specifico.

Se si desidera avere un controllo sul rendering dei controlli come html, è necessario utilizzare i controlli nello spazio dei nomi System.Web.UI.HtmlControls. Cioè:

<input type="checkbox" id="CheckBox1" runat="server" class="myClass" /> 
<input type="radio" name="RadioButton1" runat="server" class="myClass" /> 
<input type="text" id="TextBox1" runat="server" class="myClass" /> 

Essi renderanno proprio come l'elemento HTML corrispondente, senza elementi extra aggiunti. Questo ovviamente significa che dovrai assumerti la responsabilità della compatibilità del browser, in quanto il controllo no. Inoltre, questi controlli non hanno tutte le funzionalità dei controlli nello spazio dei nomi WebControls.

+0

Con quanti postbacks succedono penso che questo sarebbe più di un mal di testa. Sono d'accordo che dovremmo usare questi controlli per impostazione predefinita e passare ai WebControls quando necessario. – Mark

+14

Se hai intenzione di fare questo, potresti anche usare ASP.Net MVC;) – womp

+5

@womp Mi piacerebbe che fosse un'opzione. – Mark

5

Ogni WebControl viene convertito per impostazione predefinita come tag <span>, più qualsiasi rendering personalizzato aggiunto dall'autore del controllo.

Una delle prime cose che di solito si fa quando si scrive un WebControl personalizzato è di sovrascrivere la proprietà "TagKey" per eseguire il rendering di un div, o qualcosa di diverso da uno span. Il valore predefinito di questa proprietà è HtmlTextWriterTag.Span.

È possibile creare una sottoclasse degli elementi della casella di controllo e sovrascrivere la proprietà TagKey per eseguire il rendering di qualcos'altro, ma in tal caso è necessario eseguire tutte le checkbox nella propria versione.

+0

Immagino che tu debba scegliere il tuo veleno. Selettori jQuery brutti o controlli subclassati sporadici per rendering coerente. Sarei bello se _all_ input controlli resi con una span. La coerenza è una cosa a metà strada decente. – Mark

3

Mi sono imbattuto in questo problema e ho tentato di risolverlo utilizzando gli adattatori di controllo.

Vedere here per un esempio di come fare a un elenco di pulsanti di opzione.

ho finito con questo come la mia RadioButtonAdaptor-

using System; 
using System.Web.UI; 
using System.Web.UI.WebControls; 
using System.Web.UI.WebControls.Adapters; 

public class RadioButtonAdapter : WebControlAdapter 
{ 
    protected override void Render(HtmlTextWriter writer) 
    { 
     RadioButton targetControl = this.Control as RadioButton; 

     if (targetControl == null) 
     { 
      base.Render(writer); 

      return; 
     } 

     writer.WriteBeginTag("input"); 
     writer.WriteAttribute("type", "radio"); 
     writer.WriteAttribute("name", targetControl.GroupName); 
     writer.WriteAttribute("id", targetControl.ClientID);    

     if (targetControl.CssClass.Length > 0) 
     { 
      writer.WriteAttribute("class", targetControl.CssClass); 
     }  

     writer.Write(" />"); 

    } 
} 

E questo aggiunto ai browser File-

<browser refID="Default"> 
     <controlAdapters>    
      <adapter controlType="System.Web.UI.WebControls.RadioButton" 
       adapterType="RadioButtonAdapter" /> 
     </controlAdapters> 
</browser> 

Naturalmente, ci sono alcuni aspetti negativi a questo.Insieme a quelli menzionati allo the above link, perdi anche la funzionalità se non imponi tutto (il codice sopra non consente di controllare un pulsante radio). Ci sono alcuni adattatori di controllo CSS friendly, ma non coprono il controllo del pulsante radio. Potrebbe essere possibile utilizzare Reflector per ottenere l'adattatore di controllo predefinito come punto di partenza.

+0

Mi piace questo suggerimento! Il commento tardivo lo so, ma questo mi ha aiutato molto oggi! –

104

Anche questo mi stava facendo impazzire finché non ho trovato la proprietà inputAttributes.

Ad esempio, ecco come aggiungere una classe direttamente sul controllo casella di controllo senza l'assurdità della vita:

myCheckBoxControl.InputAttributes.Add("class", "myCheckBoxClass") 
+7

Se potessi, darei +100, dato che non riesco a dare un +1 :) Grazie! – k25

+6

Ottimo lavoro per trovarlo. Si noti inoltre che 'LabelAttributes' funziona di conseguenza per definire l'etichetta Checkbox corrispondente. – magnattic

+0

è strano perché 'myCheckBoxControl.Attributes.Add' attiverà lo stesso comportamento di' myCheckBoxControl.CssClass' dove lo avvolge in un tag '', ma 'myCheckBoxControl.InputAttributes.Add' non lo farà - yay! –

0

Trovato problema simile, ha scritto una semplice funzione basata jQuery per abilitare/casella di controllo Disattiva e arco genitore

function resetChk(ctl, bEnable) { 

      if (bEnable){ 
       ctl.removeAttr('disabled').parent().removeAttr('disabled'); 
      }else{ 
       ctl.attr('disabled', true).parent().attr('disabled', true); 
      } 

     } 
0

il modo migliore credo sia questo:

 

    public class HtmlTextWriterNoSpan : HtmlTextWriter 
    { 
     public HtmlTextWriterNoSpan(TextWriter textWriter) : base(textWriter) 
     { 
     } 

     protected override bool OnTagRender(string name, HtmlTextWriterTag key) 
     { 
      if (name == HtmlTextWriterTag.Span) 
      { 
       return false; 
      } 

      return base.OnTagRender(name, key); 
     } 
    } 
 

utilizzare i t in controllo personalizzato:

 

    protected override void Render(HtmlTextWriter writer) 
    { 
     writer = new HtmlTextWriterNoSpan(writer); 
     base.Render(writer); 
     // HERE MORE CODE 
    } 
 
1

Il semplice RadioButton viene spesso reso senza span. Se si impostano le proprietà CssClass, Style, Enabled, il RadioButton viene renderizzato con una span. Questa incoerenza è un vero dolore quando ho bisogno di manipolare il pulsante di scelta con gli script sul lato client. Quello che faccio di solito è applicare un manichino CssClass in modo che renderà sempre un'estensione coerente.

Problemi correlati