这是一个老问题,但对于我们这些不幸仍然不得不维护 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。
来源
<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
来源
<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 事件
在这一点上,显然没有任何内置控件适合,因此下一步合乎逻辑的步骤是尝试修改它们以实现所需的功能。
注意:这是基于 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事件; CommandName 和 CommandArgument 属性
- 不呈现或不依赖于突兀的 JavaScript
缺点