我想在ASP.NET网站中使用较新的<button>
标记,除其他外,它允许CSS样式的文本并在按钮内嵌入图形。 asp:Button控件呈现为<input type="button">
,有没有办法让预先存在的控件呈现给<button>
?
这是我读过有一个与IE张贴按钮的标记,而不是当按钮位于中值属性的不兼容性<form>
,但在ASP.NET将使用onclick事件无论如何,火__doPostBack,所以我不认为这会是一个问题。
我有什么理由不这样做吗?如果没有,您将如何使用asp:Button或基于它的新服务器控件来支持它?如果可以避免,我宁愿不编写我自己的服务器控件。
起初<button runat="server">
解决方案有效,但我立即遇到了需要具有CommandName属性的情况,HtmlButton控件没有这个属性。看起来我将需要创建一个从Button继承的控件。
为了覆盖渲染方法并使其呈现我想要的内容,我需要做什么?
更新
DanHerbert的回复让我有兴趣再次找到解决方案,所以我花了一些时间来研究它。
首先,有一种更容易的方法来重载TagName:
public ModernButton() : base(HtmlTextWriterTag.Button)
{
}
Dan的解决方案存在的问题是标记的innerhtml被放置在value属性中,这会导致回发时出现验证错误。一个相关的问题是,即使你正确地渲染了value属性,IE的<button>
标签的braindead实现也会发布innerhtml而不是值。所以,在此的任何实现需要重写的AddAttributesToRender方法以正确地呈现的值属性,并且还提供某种解决方法IE,因此它不能完全拧出回发。
如果要利用CommandName / CommandArgument属性进行数据绑定控件,IE问题可能无法克服。希望有人可以为此建议解决方法。
我在渲染方面取得了进展:
这将使用正确的值呈现为正确的html <button>
,但它不适用于ASP.Net PostBack系统。我已经写了一些我需要提供Command
事件的内容,但它没有触发。
当使用常规的asp:Button并排检查此按钮时,它们看起来与我需要的差异相同。所以我不确定在这种情况下ASP.Net是如何连接Command
事件的。
另一个问题是,嵌套服务器控件未呈现(正如您可以在ParseChildren(false)属性中看到的那样)。在渲染过程中将文字html文本注入控件非常容易,但是如何允许支持嵌套服务器控件呢?
答案 0 :(得分:42)
虽然你说使用[button runat =“server”]并不是一个足够好的解决方案,但重要的是要提到它 - 很多.NET程序员都害怕使用“原生”HTML标签...... / p>
使用:
<button id="btnSubmit" runat="server" class="myButton"
onserverclick="btnSubmit_Click">Hello</button>
这通常非常合适,每个人都很高兴我的团队。
答案 1 :(得分:35)
这是一个老问题,但对于我们这些不幸的人仍然需要维护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。
<强>来源
<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>
<强>来源
<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的代码,因此所有功劳都归他所有。
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
属性。这是因为本机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
属性<强>缺点强>
答案 2 :(得分:28)
我偶然发现了你的问题,寻找同样的事情。我最终使用Reflector来确定实际呈现ASP.NET Button
控件的方式。事实证明这很容易改变。
它实际上归结为覆盖TagName
类的TagKey
和Button
属性。完成后,您只需要确保手动呈现按钮的内容,因为原始Button
类从未有要呈现的内容,如果不这样,控件将呈现无文本按钮渲染内容。
更新:
可以通过继承对Button控件进行一些小的修改,但仍能正常工作。此解决方案无需为OnCommand实现自己的事件处理程序(尽管如果您想学习如何操作,我可以向您展示如何处理)。它还修复了提交其中包含标记的值的问题,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>
您还可以将控件添加到代码隐藏中按钮的控件集合中。
// 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());
我不知道这两个选项的组合效果如何,因为我没有测试过。
现在唯一的缺点就是我不认为它会记住你在PostBacks中的控件。我没有对此进行测试,因此它可能已经有效,但我对此表示怀疑。你需要为PostBacks中的子控件添加一些ViewState管理代码,但是这对你来说可能不是问题。添加ViewState支持应该不会非常困难,尽管如果需要可以轻松添加。
答案 3 :(得分:6)
您可以创建一个新控件,继承Button,并覆盖render方法,或使用.browser文件覆盖站点中的所有Buttons,类似于CSS Friendly东西对TreeView控件的工作方式等。< / p>
答案 4 :(得分:6)
您可以使用Button.UseSubmitBehavior中讨论的this article about rendering an ASP.NET Button control as a button属性。
<小时/> 编辑:对不起..这就是我在午休时间提到的问题。是否有理由不使用&lt; button runat =“server”&gt;标签还是HtmlButton?
答案 5 :(得分:2)
我会使用LinkButton并根据需要使用CSS设置样式。
答案 6 :(得分:1)
我一整天都在苦苦挣扎 - 我的自定义<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
属性。我还是没想出来。