views:

1490

answers:

4

I would expect this:

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

...to render like this (with some attributes removed for simplicity):

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

...when in fact, the RadioButton and CheckBox get wrapped with a span tag and the CSS class gets applied there.

<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" />

Is there a reason for this and is there a way to avoid it? It makes jQuery selectors ugly since you can't catch all of them with:

$("input.myClass")

Granted it is just going to:

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

...but that is ugly. I could write my own selector, but again not as elegant as it should be.

+3  A: 

Every WebControl by default renders as a <span> tag, plus any custom rendering that the control author adds.

One of the first things you usually do when you write a custom WebControl is to override the "TagKey" property to render a div, or something besides a span. The default value of this property is HtmlTextWriterTag.Span.

You could subclass your checkbox items and override the TagKey property to render something else, but then you have to deal with making all your checkboxes into your own version.

womp
I guess you have to pick your poison. Ugly jQuery selectors or sporadic subclassed controls for consistent rendering. I would be cool if _all_ input controls rendered with a span. Consistency is a half-way decent thing.
Mark
+8  A: 

Web controls in the System.Web.UI.WebControls namespace may render differently in different browsers. You can't count on them rendering the same elements always. They may add anything that they think is needed to make it work in the specific browser.

If you want to have any control over how the controls are rendered as html, you should use the controls in the System.Web.UI.HtmlControls namespace instead. That is:

<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" />

They will render just as the corresponding html element, with no extra elements added. This of course means that you will have to take responsibility for the browser compatibility, as the control doesn't. Also, those controls doesn't have all the features of the controls in the WebControls namespace.

Guffa
With how many postbacks happen I think this would be more of a headache. I agree that we should be using these controls by default and stepping up to the WebControls when needed.
Mark
If you're going to do this, you might as well just use ASP.Net MVC ;)
womp
@womp I would love that to be an option.
Mark
A: 

I came across this issue and am attempted to solve it using control adaptors.

See here for an example of doing this to a radio button list.

I ended up with this as my 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(" />");

    }
}

And this added to my browsers file-

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

Of course, there are some downsides to this. Along with those mentioned at the above link, you also lose functionality if you do not impliment everything (the above code does not allow for a radio button to be checked). There are some CSS friendly control adaptors, but they do not cover the radio button control. It may be possible to use Reflector to get the default control adaptor as a starting point.

Spongeboy
+5  A: 

This was driving me crazy too until I found the inputAttributes property.

For example, here is how to add a class directly on the checkbox control without the span nonsense:

myCheckBoxControl.InputAttributes.Add("class", "myCheckBoxClass")
JohnFx