HTML标签如何转换为HtmlControl?

时间:2016-04-12 20:56:14

标签: c# asp.net webforms

假设我有这个标记:

<asp:Repeater ID="Repeater1" runat="server">
    <ItemTemplate>
        <a runat="server" id="myLink" href="<%# Container.DataItem %>">Here</a>
    </ItemTemplate>
</asp:Repeater>

在代码隐藏中,我发现<a>已转换为HtmlAnchor

private void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    HtmlAnchor myLink = (HtmlAnchor)Repeater1.FindControl("myLink");
}

但编译器如何知道<a>HtmlAnchor?它是否在编译器中进行了硬编码?

如果我写

<asp:Repeater ID="Repeater1" runat="server">
    <ItemTemplate>
        <Foo href="<%# Container.DataItem %>">Here</a>
    </ItemTemplate>
</asp:Repeater>

并希望<Foo>标记转换为我的HtmlFoo类,我该如何实现?

我只想更深入地了解幕后的编译过程。

2 个答案:

答案 0 :(得分:2)

通过深入研究Reference Source,您可以了解很多关于ASP.NET内部的知识。

事实证明,从未加前缀的HTML标记到HtmlControl子类的映射在名为HtmlTagNameToTypeMapper的内部类中是硬编码的:

static Hashtable _tagMap;

Type ITagNameToTypeMapper.GetControlType(string tagName, IDictionary attributeBag) {
    Type controlType;

    if (_tagMap == null) {
        Hashtable t = new Hashtable(10, StringComparer.OrdinalIgnoreCase);
        t.Add("a", typeof(HtmlAnchor));
        t.Add("button", typeof(HtmlButton));
        t.Add("form", typeof(HtmlForm));
        // [and much more...]
        _tagMap = t;
    }

    // [...]
}

GetControlType由另一个名为MainTagNameToTypeMapper的内部类调用:

int colonIndex = tagName.IndexOf(':');
if (colonIndex >= 0) {
    // [...]
}
else {
    // There is no prefix.
    // Try the Html mapper if allowed
    if (fAllowHtmlTags) {
        return _htmlMapper.GetControlType(tagName, attribs);
    }
}

没有公共API可以注册更多没有前缀的HTML控件类型。

在更本地化的范围内, 可以让父控件自定义如何解释其子控件的标记名称。为此,从ControlBuilder派生,重写GetChildControlType,并使用[ControlBuilder(typeof(...)] attribute修饰父控件类。

答案 1 :(得分:0)

当您向ASP.NET中的控件添加runat="server"时,类型HtmlControl(或其某些子类)的相应变量会自动添加到您的页面中(在设计器文件中)。这样您就可以将该控件作为变量访问。对于大多数常见的HTML控件,都有HtmlControl的子类(例如HtmlAnchor用于锚点/链接标记)。其他控件(例如<div>)获取HtmlGenericControl类型。对于那些,您将标记(div)指定为属性。所以你的Foo标签就像div一样:HtmlGenericControl类型的变量,标签为“Foo”。

编辑:这适用于标准HTML元素。如果您创建ASP控件(例如<asp:TextBox...>),则生成的变量将是子类或 WebControl 而不是 HtmlControl