如何在 ASP.NET 中使用按钮标记?

新手上路,请多包涵

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

从我读到的内容来看,当按钮位于 <form> 时,IE 发布按钮的标记而不是值属性不兼容,但在 ASP.NET 中它将使用 onclick 事件来触发__doPostBack 无论如何,所以我认为这不是问题。

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


起初 <button runat="server"> 解决方案有效,但我立即遇到了它需要具有 HtmlButton 控件没有的 CommandName 属性的情况。看起来我需要创建一个继承自 Button 的控件。

我需要做什么才能覆盖 render 方法并使其呈现我想要的内容?


更新

DanHerbert 的回复让我有兴趣再次找到解决这个问题的方法,所以我花了更多的时间来解决这个问题。

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

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

Dan 的解决方案目前的问题是标记的 innerhtml 被放入 value 属性中,这会导致回发时出现验证错误。一个相关的问题是,即使您正确呈现 value 属性,IE 的 braindead 实现 <button> 标记仍然会发布 innerhtml 而不是值。因此,此方法的任何实现都需要重写 AddAttributesToRender 方法才能正确呈现 value 属性,并且还为 IE 提供某种解决方法,这样它就不会完全搞砸回发。

如果您想利用数据绑定控件的 CommandName/CommandArgument 属性,那么 IE 问题可能是无法克服的。希望有人可以为此提出解决方法。

我在渲染上取得了进展:

现代按钮.cs

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

将此按钮与常规 asp:Button 并排检查时,除了我需要的差异外,它们看起来都一样。所以我不确定在这种情况下 ASP.Net 如何连接 Command 事件。

另一个问题是,嵌套的服务器控件不会呈现(正如您可以通过 ParseChildren(false) 属性看到的那样)。在呈现期间将文字 html 文本注入控件非常容易,但是如何支持嵌套服务器控件?

原文由 Adam Lassek 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 419
2 个回答

这是一个老问题,但对于我们这些不幸的人仍然需要维护 ASP.NET Web 窗体应用程序,我在尝试将 Bootstrap 字形包含在内置按钮控件中时亲自经历了这个问题。

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

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

我需要这个标记由服务器控件呈现,所以我着手寻找选项。

按钮

这将是第一个合乎逻辑的步骤,但是 - 正如这个问题所解释的那样 - Button 呈现 <input> 元素而不是 <button> ,因此添加内部 HTML 是不可能的。

LinkButton(归功于 Tsvetomir Tsonev 的回答

资源

<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 的回答

资源

<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 的回答

注意:这是基于 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 属性(见下文)
  • 添加命名空间(以包含 @Register 指令示例)
  • 添加必要 using 指令

Value 属性只是访问旧的 Text 属性。这是因为本机 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

缺点

  • 无(除了不是内置控件)

原文由 Daniel Liuzzi 发布,翻译遵循 CC BY-SA 3.0 许可协议

虽然你说使用 [button runat=“server”] 不是一个足够好的解决方案,但重要的是要提到它 - 许多 .NET 程序员害怕使用“本机”HTML 标签……

采用:

 <button id="btnSubmit" runat="server" class="myButton"
    onserverclick="btnSubmit_Click">Hello</button>

这通常工作得很好,每个人在我的团队中都很开心。

原文由 Philippe 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题