【问题标题】:How to remove span tag from WebControl when rendered呈现时如何从 WebControl 中删除 span 标签
【发布时间】:2011-01-11 12:19:56
【问题描述】:

当使用 ASP.NET CheckBox(在其他情况下,继承自 CheckBox)时,它会在复选框输入控件周围呈现一个跨度,这个跨度控件会影响 jQuery 脚本。

渲染时可以去掉这个span吗?

【问题讨论】:

  • 你能贴一些代码吗?
  • 在这种情况下,代码太多了,无法说明问题的各种地方发布...

标签: c# asp.net web-controls html


【解决方案1】:

我刚刚遇到了这个问题并使用了 Jon 的答案,这很好,而且很有效。缺点是你的类是在代码隐藏中定义的,而不是你的标记。

所以我接受了答案,并采取了一种程序化的方式来检索控件的所有属性,将它们复制到 InputAttributes 并从属性中删除这些复制的属性。

请注意,虽然它从 RadioButton 扩展而来,但您可以使用该方法扩展任何控件,例如标签或复选框。

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

namespace Hidistro.UI.Common.Controls
{
    /// <summary>
    /// Just like a normal RadioButton, except that the wrapped span is disabled.
    /// </summary>
    public class CleanRadioButton : RadioButton
    {
        protected override void Render(HtmlTextWriter writer)
        {
            List<string> keysToRemove = new List<string>();

            foreach (object key in Attributes.Keys)
            {
                string keyString = (string)key;
                InputAttributes.Add(keyString, Attributes[keyString]);
                keysToRemove.Add(keyString);
            }

            foreach (string key in keysToRemove)
                Attributes.Remove(key);

            base.Render(writer);
        }
    }
}

这样,你只需要如下,它就会输出没有span的标签。

<namespace:CleanRadioButton class="class1" />
<namespace:CleanRadioButton class="class2" />

HTML 输出: (注意“生成”是自动生成的)

<input id="generated" type="radio" name="generated" value="generated" class="class1">
<input id="generated" type="radio" name="generated" value="generated" class="class2">

【讨论】:

    【解决方案2】:
                    <div class="onoffswitch">
                         <asp:CheckBox ID="example1" runat="server" AutoPostBack="true" OnCheckedChanged="chkWifiRequired_CheckedChanged" CssClass="aspNetDisabled onoffswitch-checkbox"/>
                        <label class="onoffswitch-label" for='<%= example1.ClientID.ToString() %>'>
                            <span class="onoffswitch-inner"></span>
                            <span class="onoffswitch-switch"></span>
                        </label>
                    </div>
    
    /* 删除涉及禁用输入的相关垃圾邮件 */ $('input[name=""]').parent('.aspNetDisabled').each(function () { var $this = $(this); var cssClass = "onoffswitch-checkbox"; $('input[name=""]').addClass(cssClass).unwrap().parent('label[for],span').first().addClass('onoffswitch-checkbox'); });

    这将允许您正常使用复选框,仍然让它调用服务器端代码,并使用引导程序中的切换。 (我使用的是 Inspina 主题,但其他切换的格式应该相同)

    【讨论】:

      【解决方案3】:

      $(document).ready(function() {
        /* remove the relative spam involving inputs disabled */
        $('input[type="checkbox"]').parent('.aspNetDisabled').each(function() {
          var $this = $(this);
          var cssClass = $this.attr('class');
          $this.children('input[type="checkbox"]').addClass(cssClass).unwrap().parent('label[for],span').first().addClass('css-input-disabled');
        });
      });
      /* CSS Example */
      .css-input {
        position: relative;
        display: inline-block;
        margin: 2px 0;
        font-weight: 400;
        cursor: pointer;
      }
      .css-input input {
        position: absolute;
        opacity: 0;
      }
      .css-input input:focus + span {
        box-shadow: 0 0 3px rgba(0, 0, 0, 0.25);
      }
      .css-input input + span {
        position: relative;
        display: inline-block;
        margin-top: -2px;
        margin-right: 3px;
        vertical-align: middle;
      }
      .css-input input + span:after {
        position: absolute;
        content: "";
      }
      .css-input-disabled {
        opacity: .5;
        cursor: not-allowed;
      }
      .css-checkbox {
        margin: 7px 0;
      }
      .css-checkbox input + span {
        width: 20px;
        height: 20px;
        background-color: #fff;
        border: 1px solid #ddd;
        -webkit-transition: background-color 0.2s;
        transition: background-color 0.2s;
      }
      .css-checkbox input + span:after {
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        font-family: "FontAwesome";
        font-size: 10px;
        color: #fff;
        line-height: 18px;
        content: "\f00c";
        text-align: center;
      }
      .css-checkbox:hover input + span {
        border-color: #ccc;
      }
      .css-checkbox-primary input:checked + span {
        background-color: #5c90d2;
        border-color: #5c90d2;
      }
      <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
      
      <!-- Generate from asp.net -->
      <label for="CheckBox1" id="Label4" class="css-input css-checkbox css-checkbox-primary">
        <span class="aspNetDisabled">
          <input id="CheckBox1" 
                 type="checkbox" 
                 checked="checked" 
                 disabled="disabled">
        </span>
        <span></span>Disabled
      </label>

      【讨论】:

      • 如果您添加一些解释和文档链接,答案会变得更有价值,因此原始发布者和其他用户实际上可以从中学习。
      【解决方案4】:

      我不知道这是否适用于这个特定的示例。但是,如果您制作自己的 WebControl 并且您不希望它围绕自身呈现跨度,您可以像这样覆盖 Controls 渲染方法:

      public class MyWebControl : WebControl
      {
      
        /* Your code 
                   between here */
      
        protected override void Render(HtmlTextWriter writer)
        {
          RenderContents (writer);
        }
      }
      

      我想您可以将相同的内容添加到继承的 CheckBox... 类似这样:

      public class MyCheckBox : CheckBox 
      {
      
        /* Your code 
                   between here */
      
        protected override void Render(HtmlTextWriter writer)
        {
          RenderContents (writer);
        }
      }
      

      解决方案的基本问题在这里更好地解释:
      http://www.marten-online.com/net/stripping-span-tag-from-webcontrol.html

      【讨论】:

        【解决方案5】:

        使用 Jquery

        <script>
                $(".selector input").unwrap().addClass("cssclass");
        </script>
        

        【讨论】:

          【解决方案6】:

          我想知道,no1 提到这一点是否有原因:

          public MyControl() : base(string.Empty)
          

          我读到了 flaviotsf 提到的http://aspnetresources.com/blog/stripping_span_from_webcontrol

          【讨论】:

          • 它为我产生 > 输出。
          • 你点击我提供的链接了吗?
          • 文章包含另一种解决方案。
          【解决方案7】:
              protected override HtmlTextWriterTag TagKey
              {
                  get
                  {              
                      return HtmlTextWriterTag.Div;
                  }
              }
          

          应该这样做

          【讨论】:

            【解决方案8】:

            我发现通过实现如下所示的构造函数,您可以为控件指定容器标记。

            public MyCustomControl() : base(HtmlTextWriterTag.Div)
            {
            }
            

            您可以将HtmlTextWriterTag 替换为任何可用的选项,例如上例中的 Div。默认为Span

            【讨论】:

              【解决方案9】:

              在过去的 3 个小时里,我一直在努力寻找解决这个问题的方法。

              结果如下:

              using System.Web.UI;
              using System.Web.UI.WebControls;
              
              /// <summary>
              /// Represents a custom checkbox web control.
              /// Prevents itself to be wrapped into a <span> tag when disabled.
              /// </summary>
              public class CustomCheckBox : CheckBox
              {
                  /// <summary>
                  /// Renders the control to the specified HTML writer.
                  /// </summary>
                  /// <param name="writer">The HtmlTextWriter object that receives the control content.</param>
                  protected override void Render(HtmlTextWriter writer)
                  {
                      // Use custom writer
                      writer = new HtmlTextWriterNoSpan(writer);
              
                      // Call base class
                      base.Render(writer);
                  }
              }
              

              除了自定义控件,您还需要一个自定义 HtmlTextWriter:

              using System.IO;
              using System.Web.UI;
              
              /// <summary>
              /// Represents a custom HtmlTextWriter that displays no span tag.
              /// </summary>
              public class HtmlTextWriterNoSpan : HtmlTextWriter
              {
                  /// <summary>
                  /// Constructor.
                  /// </summary>
                  /// <param name="textWriter">Text writer.</param>
                  public HtmlTextWriterNoSpan(TextWriter textWriter)
                      : base(textWriter)
                  { }
              
                  /// <summary>
                  /// Determines whether the specified markup element will be rendered to the requesting page.
                  /// </summary>
                  /// <param name="name">Name.</param>
                  /// <param name="key">Tag key.</param>
                  /// <returns>True if the markup element should be rendered, false otherwise.</returns>
                  protected override bool OnTagRender(string name, HtmlTextWriterTag key)
                  {
                      // Do not render <span> tags
                      if (key == HtmlTextWriterTag.Span)
                          return false;
              
                      // Otherwise, call the base class (always true)
                      return base.OnTagRender(name, key);
                  }
              }
              

              仅供参考,使用:

              checkbox.InputAttributes.Add("disabled", "disabled");
              

              具有相同的效果,但是:

              1. 不如checkbox方便。Enalbed = false;
              2. 当复选框位于 ListView 中时,该属性在回发后被删除。

              【讨论】:

              • 这成功摆脱了span,但是现在你不能在复选框中添加css类。好主意!
              【解决方案10】:

              发现这个有用的提示:

              在 Code Behind 中,使用 InputAttributes 而不是 Attributes。

              例如,输入:

              chk.InputAttributes.Add("onchange", "updateFields()")
              

              而不是这个:

              chk.Attributes.Add("onchange", "updateFields()")
              

              或代替内联声明:

              <asp:CheckBox ID="chk" runat="server" onchange="updateFields()" />
              

              最后两个将导致环绕跨度。

              【讨论】:

                【解决方案11】:

                尝试向您的类添加一个如下所示的构造函数:

                public MyControl() : base() 
                {
                }
                

                如果您注意到,控件将默认呈现为 span,因为这就是“WebControl”所使用的(如果您使用 Reflector):

                protected WebControl() : this(HtmlTextWriterTag.Span) { }
                

                参考: http://aspnetresources.com/blog/stripping_span_from_webcontrol

                【讨论】:

                  【解决方案12】:

                  您可以使用文字控件来代替吗?这两种选择有很大区别:

                  <p>12345<asp:Label ID="lblMiddle" runat="server" Text="6"></asp:Label>7890</p>
                  <p>12345<asp:Literal ID="ltlMiddle" runat="server" Text="6"></asp:Literal>7890</p>
                  

                  【讨论】:

                    【解决方案13】:

                    我刚刚在测试页面上尝试过这个,但我没有得到我的 CheckBox 控件...你确定是 CheckBox 呈现这个吗?有条件吗?

                    更新:好的,它似乎取决于 CheckBox 是否具有额外的属性,包括 CssClass 设置...或“禁用”属性。

                    【讨论】:

                    • 是的,似乎所有样式都添加到了一个包含复选框输入控件的跨度中。如果我从 Control 而不是复选框继承,我似乎可以摆脱跨度,尽管我必须重新实现几乎每个属性,例如呈现为 onclick 的 OnClientClick 属性。我正在使用其他(非 .net 或自定义属性,正如您所提到的,这也可能是原因)我认为从 asp.net CheckBox 继承并消除跨度的能力很容易,但似乎并非如此。跨度>
                    • 我会接受尼克的建议并覆盖 Render 方法。您可以通过使用原始 CheckBox 渲染方法(从 Reflector 剪切和粘贴)来走捷径,只需拉出 span 标签。
                    • 感谢这一点,即使 CssClass 设置为空字符串也会发生。
                    【解决方案14】:

                    为什么不使用 .remove 和 jquery 删除跨度?

                    【讨论】:

                    • 因为&lt;span /&gt; 包装了&lt;input /&gt; 标签,正确地做会非常低效。
                    • 虽然我很喜欢jQuery,它可以解决问题,但我更喜欢在更低的层次上解决问题,这样效率会更高。
                    【解决方案15】:

                    不需要标签的可以直接使用input/checkbox控件,也可以自己放一个:

                    <input type="checkbox" id="CheckBox1" runat="server" />
                    <label for="CheckBox1">My Label</label>
                    

                    CSS 适配器可能能够移除复选框/标签周围的跨度,但我还没有看到用于此目的的。

                    【讨论】:

                    • 标签妨碍我时,我不得不使用这种方法。
                    • 我可以直接使用 标签,但是我们派生的 CheckBox 包含一个可以使用的命令事件。理想情况下,我们希望在 WebControl 中解决这个问题。
                    • @Mark - 如果这不是一个选项,您可以从 Checkbox 继承,覆盖渲染,或者调用它的 SetRenderMethodDelegate() 方法。 Rick Strahl 在这里对其进行了简要介绍:west-wind.com/Weblog/posts/6138.aspx
                    猜你喜欢
                    • 2020-03-16
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-02-14
                    • 2011-05-20
                    • 2014-04-25
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多