为什么ASP.Net RadioButton和CheckBox在一个范围内呈现?

我会期待这一点:

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

…像这样渲染(为简单起见删除了一些属性)

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

…实际上, RadioButtonCheckBoxspan标记包裹,并且CSS类被应用在那里。

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

有没有这个原因,有没有办法避免它? 这使得jQueryselect器变得丑陋,因为你无法捕捉到所有这些:

 $("input.myClass") 

授予它只是要:

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

…但这是丑陋的。 我可以编写自己的select器,但又不像应该那样高雅。

System.Web.UI.WebControls命名空间中的Web控件可能在不同的浏览器中呈现不同的效果。 你不能指望他们始终呈现相同的元素。 他们可能会添加任何他们认为需要使其在特定浏览器中工作的内容。

如果您想要控制如何将控件呈现为html,则应该使用System.Web.UI.HtmlControls命名空间中的控件。 那是:

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

它们将像相应的html元素一样渲染,不会添加额外的元素。 这当然意味着你将不得不承担浏览器兼容性的责任,因为控制器不兼容。 此外,这些控件不具有WebControls命名空间中控件的所有function。

直到findinputAttributes属性,这也让我发疯。

例如,这里是如何直接添加一个类的checkbox控件没有跨度废话:

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

每个WebControl默认呈现为一个<span>标记,以及控制作者添加的任何自定义呈现。

当你编写一个自定义的WebControl时,你通常会做的第一件事情就是重写“ TagKey ”属性来渲染一个div,或者除了span之外的东西。 该属性的默认值是HtmlTextWriterTag.Span。

你可以inheritance你的checkbox项目并覆盖TagKey属性来渲染其他东西,但是你必须处理所有的checkbox到你自己的版本。

我遇到了这个问题,并试图使用控制适配器来解决它。

在这里看到这样一个单选button列表的例子。

我结束了这个作为我的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(" />"); } } 

这添加到我的浏览器文件 –

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

当然,这有一些缺点。 除了上面提到的那些链接 ,如果你不提示所有东西(上面的代码不允许单选button被选中),你也会失去function。 有一些CSS友好的控制适配器,但不包括单选button控件。 可以使用Reflector来获取默认的控制适配器作为起点。

简单的RadioButton通常是没有跨度的渲染。 如果您设置了CssClass,Style,Enabled属性,则RadioButton会以一个范围呈现。 当我需要使用客户端脚本来操作单选button时,这种不一致是一个真正的痛苦。 我通常做的是应用一个虚拟的CssClass,以便始终呈现一个跨度。

发现类似的问题,写了一个简单的基于jQuery的函数来启用/禁用checkbox和父跨度

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

我认为最好的办法是这样的:

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); } }
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); } } 

在自定义控件中使用它:

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