我想在ASP.NET网站中使用较新的<button>标记,该标记除其他事项外,允许CSS样式的文本并将图形嵌入按钮内。 asp:Button控件呈现为<input type="button">,是否有任何方法可以将现有控件呈现为<button>

据我了解,当按钮位于<form>内时,IE发布按钮的标记而不是value属性与IE不兼容,但是在ASP.NET中,无论如何它将使用onclick事件触发__doPostBack,所以我不这样做认为这不会成为问题。

有什么原因为什么我不应该使用这个?如果没有,您将如何使用asp:Button或基于它的新服务器控件来支持它?如果可以避免,我宁愿不编写自己的服务器控件。

最初,<button runat="server">解决方案起作用了,但是我立即遇到一种情况,它需要具有CommandName属性,而HtmlButton控件则没有。看来我毕竟需要创建一个从Button继承的控件。

为了覆盖render方法并使它渲染我想要的东西,我需要做什么?

更新

DanHerbert的回复使我有兴趣再次找到解决方案,因此我花了更多时间进行处理。

首先,有一种更简单的方法来重载TagName:

public ModernButton() : base(HtmlTextWriterTag.Button)
{
}

Dan的解决方案存在的问题是将标记的innerhtml放在value属性中,这会导致回发时发生验证错误。一个相关的问题是,即使您正确地呈现了value属性,IE的<button>标记的Braindead实现也张贴了innerhtml而不是值。因此,此方法的任何实现都需要重写AddAttributesToRender方法,以便正确呈现value属性,并且还为IE提供某种解决方法,因此不会完全破坏回发。

如果要对数据绑定(bind)控件使用CommandName/CommandArgument属性,则IE问题可能是无法克服的。希望有人可以为此建议解决方法。

我在渲染方面取得了进展:

ModernButton.cs

这将呈现为具有正确值的正确html <button>,但不适用于ASP.Net PostBack系统。我已经写了一些需要提供Command事件的内容,但是没有触发。

与常规asp:Button并排检查此按钮时,除了我需要的区别之外,它们看起来相同。因此,在这种情况下,我不确定ASP.Net如何连接Command事件。

另一个问题是,不呈现嵌套的服务器控件(如使用ParseChildren(false)属性所见)。在渲染过程中将文字html文本注入(inject)控件很容易,但是如何允许对嵌套服务器控件的支持呢?

最佳答案

这是一个古老的问题,但是对于我们中那些不幸的人,他们仍然必须维护ASP.NET Web Forms应用程序,我自己经历了此尝试,同时尝试将Bootstrap字形包含在内置按钮控件中。

根据Bootstrap文档,所需的标记如下:

<button class="btn btn-default">
    <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
    Search
</button>

我需要通过服务器控件来呈现此标记,因此我着手查找选项。

纽扣

这将是逻辑上的第一步,但是-正如该问题所解释的-Button呈现<input>元素而不是<button>,因此无法添加内部HTML。

LinkBut​​ton(贷给Tsvetomir Tsonev's answer)

来源

<asp:LinkButton runat="server" ID="uxSearch" CssClass="btn btn-default">
    <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
    Search
</asp:LinkButton>

输出

<a id="uxSearch" class="btn btn-default" href="javascript:__doPostBack(&#39;uxSearch&#39;,&#39;&#39;)">
    <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
    Search
</a>

优点
  • 看起来不错
  • Command事件; CommandNameCommandArgument属性

  • 缺点
  • 呈现<a>而不是<button>
  • 呈现并依赖于干扰性的JavaScript

  • HtmlButton(记入Philippe's answer)

    来源

    <button runat="server" id="uxSearch" class="btn btn-default">
        <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
        Search
    </button>
    

    结果

    <button onclick="__doPostBack('uxSearch','')" id="uxSearch" class="btn btn-default">
        <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
        Search
    </button>
    

    优点
  • 看起来不错
  • 渲染适当的<button>元素

  • 缺点
  • 没有Command事件;没有CommandNameCommandArgument属性
  • 呈现并依赖于干扰性JavaScript来处理其ServerClick事件


  • 在这一点上很明显,没有内置控件似乎合适,因此下一步的逻辑步骤是尝试对其进行修改以实现所需的功能。

    自定义控件(贷给Dan Herbert's answer)

    注意:这是基于Dan的代码的,所以所有的功劳都归功于他。

    using System.Web.UI;
    using System.Web.UI.WebControls;
    
    namespace ModernControls
    {
        [ParseChildren]
        public class ModernButton : Button
        {
            public new string Text
            {
                get { return (string)ViewState["NewText"] ?? ""; }
                set { ViewState["NewText"] = value; }
            }
    
            public string Value
            {
                get { return base.Text; }
                set { base.Text = value; }
            }
    
            protected override HtmlTextWriterTag TagKey
            {
                get { return HtmlTextWriterTag.Button; }
            }
    
            protected override void AddParsedSubObject(object obj)
            {
                var literal = obj as LiteralControl;
                if (literal == null) return;
                Text = literal.Text;
            }
    
            protected override void RenderContents(HtmlTextWriter writer)
            {
                writer.Write(Text);
            }
        }
    }
    

    我将类降至最低限度,并对其进行了重构,以使用尽可能少的代码来实现相同的功能。我还添加了一些改进。即:
  • 删除PersistChildren属性(似乎不必要)
  • 删除TagName覆盖(似乎不必要)
  • Text中删除HTML解码(基类已经处理过)
  • 保留OnPreRender完整;改写AddParsedSubObject(更简单)
  • 简化RenderContents覆盖
  • 添加Value属性(如下所示)
  • 添加一个 namespace (以包括 @ Register 指令示例)
  • 添加必要的using指令
  • Value属性仅访问旧的Text属性。这是因为 native 的Button控件始终会渲染value属性(以Text作为其值)。由于value<button>元素的有效属性,因此我决定为其添加一个属性。

    来源

    <%@ Register TagPrefix="mc" Namespace="ModernControls" %>
    
    <mc:ModernButton runat="server" ID="uxSearch" Value="Foo" CssClass="btn btn-default" >
        <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
        Search
    </mc:ModernButton>
    

    输出

    <button type="submit" name="uxSearch" value="Foo" id="uxSearch" class="btn btn-default">
        <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
        Search
    </button>
    

    优点
  • 看起来不错
  • 渲染适当的<button>元素
  • Command事件; CommandNameCommandArgument属性
  • 不呈现或不依赖于干扰性JavaScript

  • 缺点
  • 无(不是内置控件)
  • 10-05 22:33
    查看更多