为啥 ASP.Net RadioButton 和 CheckBox 在 Span 内呈现?

Posted

技术标签:

【中文标题】为啥 ASP.Net RadioButton 和 CheckBox 在 Span 内呈现?【英文标题】:Why does ASP.Net RadioButton and CheckBox render inside a Span?为什么 ASP.Net RadioButton 和 CheckBox 在 Span 内呈现? 【发布时间】:2010-11-03 02:20:52 【问题描述】:

我希望这样:

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

这是有原因的吗?有办法避免吗?它使 jQuery 选择器变得丑陋,因为您无法捕获所有选择器:

$("input.myClass")

当然它只是:

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

...但这很难看。我可以编写自己的选择器,但还是没有应有的优雅。

【问题讨论】:

不是答案,只是表示同情——几年前我第一次开始在 .NET 平台上工作并使用 JS 找出复选框的值时,我花了几个小时试图弄清楚为什么我的价值观没有引起警觉。你猜怎么着——跨度标签。我一直想知道为什么 MS 为他们的单选按钮和复选框添加了冗余标签! @Hardwareguy 有时这是跨度,有时是输入。那就是问题所在。 $("input.myclass") 可能有点过于具体,但 $(".myClass") 会让你同样头疼。 如果您使用 Checkbox.Text 属性,则会添加一个标签。然后跨度将围绕它们,并且样式适用于两者。这就是周围跨度的原因。 可能是因为这样的事情:***.com/questions/7398462/… 对于 asp:checkbox,我注意到使用 CssClass 属性时也会添加跨度。 【参考方案1】:

在我找到 inputAttributes 属性之前,这也让我发疯了。

例如,这里是如何直接在复选框控件上添加一个类,而不需要跨度废话:

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

【讨论】:

如果可以,我会给 +100,因为我不能给 +1 :) 谢谢! 很好地找到了这个。另请注意,LabelAttributes 会相应地设置相应复选框标签的样式。 这很奇怪,因为myCheckBoxControl.Attributes.Add 将触发与myCheckBoxControl.CssClass 相同的行为,它将其包装在&lt;span&gt; 标记中,但myCheckBoxControl.InputAttributes.Add 不会 - 耶! 不幸的是,使用此方法添加的类不会在视图状态中捕获,而使用 CssClass 添加的类会在视图状态中捕获。 在哪里添加这个。我无法在 c# 后面的代码中获取 InputAttributes【参考方案2】:

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 命名空间中控件的所有功能。

【讨论】:

发生了多少回发,我认为这会更令人头疼。我同意我们应该默认使用这些控件,并在需要时升级到 WebControls。 如果你打算这样做,你还不如只使用 ASP.Net MVC ;) @womp 我希望这是一个选项。【参考方案3】:

默认情况下,每个 WebControl 都呈现为 &lt;span&gt; 标记,以及控件作者添加的任何自定义呈现。

在编写自定义 WebControl 时,您通常要做的第一件事就是覆盖“TagKey”属性以呈现 div 或跨度以外的其他内容。该属性的默认值为 HtmlTextWriterTag.Span。

您可以将您的复选框项目子类化并覆盖 TagKey 属性以呈现其他内容,但是您必须处理将所有复选框变成您自己的版本。

【讨论】:

我猜你必须选择你的毒药。丑陋的 jQuery 选择器或零星的子类控件以实现一致的渲染。如果 all 输入控件使用跨度呈现,我会很酷。一致性是一件不错的事情。【参考方案4】:

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

有关对单选按钮列表执行此操作的示例,请参阅 here。

我最终将它作为我的 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>

当然,这也有一些缺点。与the above link 中提到的那些一样,如果您不隐含所有内容,您也会失去功能(上面的代码不允许检查单选按钮)。有一些 CSS 友好的控件适配器,但它们不包括单选按钮控件。或许可以使用Reflector来获取默认的控制适配器作为起点。

【讨论】:

我喜欢这个建议!我知道迟到的评论,但这对我今天帮助很大!【参考方案5】:

普通的 RadioButton 通常在没有跨度的情况下呈现。如果设置了 CssClass、Style、Enabled 属性,RadioButton 会以跨度呈现。当我需要使用客户端脚本操作单选按钮时,这种不一致是一个真正的痛苦。我通常做的是应用一个虚拟的 CssClass,以便它始终一致地呈现一个跨度。

【讨论】:

【参考方案6】:

我认为最好的方法是:

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

【讨论】:

我喜欢那个【参考方案7】:

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

function resetChk(ctl, bEnable)  

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

        

【讨论】:

以上是关于为啥 ASP.Net RadioButton 和 CheckBox 在 Span 内呈现?的主要内容,如果未能解决你的问题,请参考以下文章

asp.net(C#)怎样将listview中的radiobutton设置成互斥?

ASP.NET C#中Radiobutton控件的疑问

asp.net中radiobutton 的问题 C#

ASP.NET C#中Radiobutton控件的疑问

ASP.NET RadioButton 与名称(组名)混淆

向 asp.NET RadioButton 控件添加自定义属性