我想在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。LinkButton(贷给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('uxSearch','')">
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
Search
</a>
优点
Command
事件; CommandName
和CommandArgument
属性缺点
<a>
而不是<button>
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
事件;没有CommandName
或CommandArgument
属性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
属性(如下所示)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
事件; CommandName
和CommandArgument
属性缺点