【问题标题】: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 属性,则会添加一个标签。然后跨度将围绕它们,并且样式适用于两者。这就是周围跨度的原因。
  • 可能是因为这样的事情:stackoverflow.com/questions/7398462/…
  • 对于 asp:checkbox,我注意到使用 CssClass 属性时也会添加跨度。

标签: asp.net webforms


【解决方案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);
                }
    
            }
    

    【讨论】:

      猜你喜欢
      • 2018-12-10
      • 2011-03-27
      • 2011-12-29
      • 2016-08-20
      • 2014-03-21
      • 1970-01-01
      • 2013-12-31
      • 1970-01-01
      • 2012-04-12
      相关资源
      最近更新 更多