如何在WebControl渲染时删除span标签

17

在使用ASP.NET CheckBox时(在我们的案例中,是从CheckBox继承而来),它会在复选框输入控件周围呈现一个元素,这个元素会影响jQuery脚本。

在渲染时是否可能移除这个元素?


你能贴一些代码吗? - Hannoun Yassir
在这种情况下,有太多的代码需要发布到各种不会说明问题的地方... - Mark Redman
15个回答

36

发现了这个有用的提示:

在后台代码中,使用InputAttributes而不是Attributes。

例如,输入以下内容:

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

使用这个替代:

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

或者使用内联声明的替代方法:

<asp:CheckBox ID="chk" runat="server" onchange="updateFields()" />
最后两个将使包装span。

10

我在测试页面上尝试了这个方法,但是复选框控件周围没有边框...你确定是复选框导致的吗?这是有条件的吗?

更新:好的,看起来这取决于复选框是否具有额外的属性,包括CssClass设置...或者“disabled”属性。


是的,似乎所有样式都添加到包装复选框输入控件的span中。如果我从Control而不是checkbox继承,则可以消除span,尽管我必须重新实现几乎每个属性,例如OnClientClick属性,它呈现为onclick。我正在使用其他(非.net或自定义属性,正如您提到的可能也是原因)。我认为从asp.net CheckBox继承并消除span的能力应该很容易,但似乎并不是这样。 - Mark Redman
那我会采纳Nick的建议,重写Render方法。你可以通过使用原始的CheckBox渲染方法(从Reflector中剪切和粘贴)并仅提取span标记来快捷实现。 - Bryan
谢谢,即使CssClass设置为空字符串也会发生这种情况。 - Andrew Afternoon-Delight Hayde

9

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

public class MyWebControl : WebControl
{

  /* Your code 
             between here */

  protected override void Render(HtmlTextWriter writer)
  {
    RenderContents (writer);
  }
}

我猜你可以将相同的内容添加到继承的复选框中...就像这样:
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

该链接提供了关于去除Web控件中标签的更详细解释。

4

我花了最近的三个小时绞尽脑汁寻找这个问题的解决方案。

以下是我的结论:

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中时,在postback后该属性将被移除。

这样可以成功去除 span,但是现在你无法为复选框添加 CSS 类。不过想法不错! - EJC

3
使用jQuery
<script>
        $(".selector input").unwrap().addClass("cssclass");
</script>

2
    protected override HtmlTextWriterTag TagKey
    {
        get
        {              
            return HtmlTextWriterTag.Div;
        }
    }

应该做什么


1
你可以使用字面控件吗?这两种选择之间有很大的区别:
<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>

1
我发现通过实现以下类似的构造函数,您可以指定控件的容器标签。
public MyCustomControl() : base(HtmlTextWriterTag.Div)
{
}

你可以将HtmlTextWriterTag替换为任何可用选项,比如上面的示例中的Div。默认值是Span

1

如果您不需要标签,可以直接使用输入/复选框控件,或者自己添加一个:

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

一个CSS适配器可能能够移除复选框/标签周围的span,但我还没有看到为此而设计的适配器。

当<span>标签妨碍了我的工作时,我不得不采用这种方法。 - egrunin
1
我可以直接使用<input>标签,但是我们的派生CheckBox包括了可以使用的Command Event。理想情况下,我们希望在WebControl中解决这个问题。 - Mark Redman
@Mark - 如果那不是一个选项,你可以继承自Checkbox,覆盖渲染,或者调用它的SetRenderMethodDelegate()方法。Rick Strahl在这里详细介绍了它:http://www.west-wind.com/Weblog/posts/6138.aspx - Nick Craver

1
为什么不使用jQuery中的.remove来移除span?

1
因为 <span /> 包裹了 <input /> 标签,如果正确处理会非常低效。 - Dan Herbert
2
虽然我非常喜欢jQuery,它可以解决问题,但我更愿意在更低的层次上解决问题,这样会更有效率。 - Mark Redman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接