如何使用ASP.NET的button标签?

我想在ASP.NET网站中使用更新的<button>标签,其中包括允许使用CSS样式的文本并在button内embeddedgraphics。 asp:Button控件呈现为<input type="button"> ,有什么办法可以将一个预先存在的控件呈现给<button>

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

有什么理由不能使用这个吗? 如果没有,你将如何去支持与ASP:button,或基于它的新的服务器控制? 如果可以避免,我宁愿不写我自己的服务器控件。


起初, <button runat="server">解决scheme工作,但我立即遇到一个情况,需要有一个CommandName属性,HtmlButton控件没有。 看起来我需要创build一个从Buttoninheritance的控件。

我需要做什么来覆盖渲染方法,并使其呈现我想要的?


UPDATE

DanHerbert的回答使我有兴趣再次find解决办法,所以我花了更多的时间在这方面进行研究。

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

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

丹的解决scheme,因为它的问题是标签的innerhtml被放置到值属性,这会导致回发validation错误。 一个相关的问题是,即使你正确地呈现了value属性,IE的braindead实现的<button>标签发布的innerhtml而不是价值。 所以,这个任何实现都需要重写AddAttributesToRender方法,以便正确呈现值属性,并且还为IE提供某种解决方法,所以它不会完全搞砸回发。

IE的问题可能是不可逾越的,如果你想利用CommandName / CommandArgument属性的数据绑定控件。 希望有人可以为此提出解决方法。

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

ModernButton.cs

这呈现为一个正确的HTML <button>具有正确的值,但它不能与ASP.Net PostBack系统一起使用。 我写了一些我需要提供Command事件,但它不会触发。

当用一个普通的asp:Button检查这个button时,它们看起来与我所需要的不同。 所以我不确定在这种情况下ASP.Net如何连接Command事件。

另外一个问题是,嵌套的服务器控件不能被渲染(你可以看到ParseChildren(false)属性)。 在渲染过程中将直接的html文本注入控件非常容易,但是如何支持嵌套的服务器控件呢?

    7 Solutions collect form web for “如何使用ASP.NET的button标签?”

    这是一个古老的问题,但对于我们这些仍然不得不维护ASP.NET Web窗体应用程序的人来说,我自己也尝试在内置button控件中包含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的答案 )

    资源

     <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(相信菲利普的答案 )

    资源

     <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事件

    在这一点上,显然没有任何内置的控件看起来合适,所以下一个合理的步骤是尝试并修改它们以实现所需的function。

    自定义控制( 丹·赫伯特的答案 )

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

     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); } } } 

    我已经把课程剥离到了最低限度,并且重构了它,以尽可能less的代码实现相同的function。 我还添加了一些改进。 即:

    • 删除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

    缺点

    • 没有(除了不是一个内置的控制)

    虽然你说使用[button runat =“server”]并不是一个好的解决scheme,但重要的是要提到它 – 许多.NET程序员害怕使用“native”HTML标签。

    使用:

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

    这通常工作得很好,每个人都为我的团队感到高兴。

    我偶然发现了同样的问题。 我结束了使用Reflector找出如何实际呈现ASP.NET Button控件。 事实certificate很容易改变。

    这真的只是重写Button类的TagNameTagKey属性。 完成之后,您只需确保您手动呈现button的内容,因为原始的Button类从未拥有要呈现的内容,并且如果不呈现内容,控件将呈现无文本button。

    更新:

    可以通过inheritance对Button控件做一些小的修改,并且仍然可以很好地工作。 这个解决scheme消除了为OnCommand实现自己的事件处理程序的需要(尽pipe如果你想学习如何做,我可以告诉你如何处理)。 它也解决了提交一个具有标记的值的问题,除了IE可能。 我仍然不知道如何解决IE浏览器的Button标签不好的实现。 这可能只是一个真正的技术限制,是不可能解决的…

     [ParseChildren(false)] [PersistChildren(true)] public class ModernButton : Button { protected override string TagName { get { return "button"; } } protected override HtmlTextWriterTag TagKey { get { return HtmlTextWriterTag.Button; } } // Create a new implementation of the Text property which // will be ignored by the parent class, giving us the freedom // to use this property as we please. public new string Text { get { return ViewState["NewText"] as string; } set { ViewState["NewText"] = HttpUtility.HtmlDecode(value); } } protected override void OnPreRender(System.EventArgs e) { base.OnPreRender(e); // I wasn't sure what the best way to handle 'Text' would // be. Text is treated as another control which gets added // to the end of the button's control collection in this //implementation LiteralControl lc = new LiteralControl(this.Text); Controls.Add(lc); // Add a value for base.Text for the parent class // If the following line is omitted, the 'value' // attribute will be blank upon rendering base.Text = UniqueID; } protected override void RenderContents(HtmlTextWriter writer) { RenderChildren(writer); } } 

    要使用此控件,您有几个选项。 一种是将控件直接放在ASP标记中。

     <uc:ModernButton runat="server" ID="btnLogin" OnClick="btnLogin_Click" Text="Purplemonkeydishwasher"> <img src="../someUrl/img.gif" alt="img" /> <asp:Label ID="Label1" runat="server" Text="Login" /> </uc:ModernButton> 

    您也可以将控件添加到代码隐藏button的控件集合中。

     // This code probably won't work too well "as is" // since there is nothing being defined about these // controls, but you get the idea. btnLogin.Controls.Add(new Label()); btnLogin.Controls.Add(new Table()); 

    我不知道这两个选项的组合有多好,因为我没有testing过。

    这个控件现在唯一的缺点是我不认为它会记住你的控件在PostBacks上。 我没有testing过,所以它可能已经工作,但我怀疑它。 你需要添加一些ViewStatepipe理代码来处理跨越PostBacks的子控件,但是这可能不是你的问题。 添加ViewState支持不是非常难,尽pipe如果需要,可以很容易地添加。

    你可以创build一个新的控件,从Buttoninheritance,重写render方法,或者使用.browser文件覆盖站点中的所有button,类似于CSS友好的东西为TreeView控件工作的方式。

    您可以使用本文中讨论的Button.UseSubmitBehavior属性来将ASP.NET Button控件渲染为button 。


    编辑:对不起。这就是我在午休时偷看问题。 有没有理由不使用<button runat =“server”>标签或HtmlButton ?

    我会去与LinkBut​​ton,并适当的样式与CSS。

    我一直在努力整天 – 我的自定义<button/>生成的控件不能正常工作:

    System.Web.HttpRequestValidationException:从客户端检测到有潜在危险的Request.Form值

    会发生什么是.Net添加一个name属性:

     <button type="submit" name="ctl02" value="Content" class="btn "> <span>Content</span> </button> 

    在使用IE 6和IE 7时, name属性会引发服务器错误。在其他浏览器(Opera,IE 8,Firefox,Safari)中一切正常。

    治愈的方法是破解那个name属性。 但我还没有想出来。