如何使用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文本注入控件非常容易,但是如何支持嵌套的服务器控件呢?
这是一个古老的问题,但对于我们这些仍然不得不维护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是不可能的。
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('uxSearch','')"> <span class="glyphicon glyphicon-search" aria-hidden="true"></span> Search </a>
优点
- 看起来不错
-
Command
事件;CommandName
和CommandArgument
属性
缺点
- 呈现
<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
事件; 没有CommandName
或CommandArgument
属性 - 渲染并依赖强大的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
事件;CommandName
和CommandArgument
属性 - 不渲染或依赖强大的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
类的TagName
和TagKey
属性。 完成之后,您只需确保您手动呈现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 ?
我会去与LinkButton,并适当的样式与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
属性。 但我还没有想出来。