控制 ASP.NET 頁面解析器如何處理控件標籤內部內容,透過 [PersistChildren(false)] 關閉預設屬性解析,配合自訂 ControlBuilder 在編譯期接管解析邏輯,實現「我的地盤我做主」。
<asp:DropDownList>
<asp:ListItem Value="1">1</asp:ListItem>
<asp:ListItem Value="2">2</asp:ListItem>
</asp:DropDownList>
ListItem 標籤內文字("1"、"2")自動解析為 Text 屬性,因 ListItem 標記 [ParseChildren(true, "Text")]。
[ParseChildren(true)]:內容解析為屬性(預設用內建解析器處理屬性、子屬性、模板、集合)[ParseChildren(true, "PropertyName")]:指定預設屬性接收內容[ParseChildren(false)]:內容不解析為屬性,改由 ControlBuilder 處理[ControlBuilder(typeof(ListItemControlBuilder))]
public sealed class ListItem : IStateManager, IParserAccessor, IAttributeAccessor { }
public class ListItemControlBuilder : ControlBuilder
{
public override bool AllowWhitespaceLiterals() => false; // 去除首尾空白
public override bool HtmlDecodeLiterals() => true; // 解碼 HTML 實體
}
[ParseChildren(false)]
public class MyControl : WebControl
{
protected override void AddParsedSubObject(object obj)
{
if (obj is LiteralControl literal)
Text = literal.Text;
else
throw new ArgumentException("僅允許靜態文字內容");
}
}
效能差異:ControlBuilder 僅在頁面編譯/解析階段執行一次;AddParsedSubObject 每次請求都執行。優先使用 ControlBuilder。
WebControl 且需自訂解析:必須 加 [ParseChildren(false)],否則預設屬性解析優先生效AllowWhitespaceLiterals、HtmlDecodeLiteralsControlBuilder.GetChildControlType、AppendLiteralString 中實作