怎樣更改默認的控件分析邏輯
------用PersistChildren(false)和ControlBuilder來定制ASP.net對控件標簽對中的內容的分析
“我的地盤,我做主”
寫到這裡,我把foobar播放的音樂換成了周傑倫的歌,雖然不是“我的地盤”。
我們來回顧一下第三篇中的一段代碼:
<asp:DropDownList id="DropDownList1" runat="server" Font-Bold="True">
<asp:ListItem Value="1">1</asp:ListItem>
<asp:ListItem Value="2">2</asp:ListItem>
</asp:DropDownList>
我不知大家有沒有注意到一個現象,<asp:ListItem>內含的內容不能有頁面對象,那麼如果有了分析器如何來處理呢?。這就透露了一個信息給我們,對於頁面元素的分析處理,我們是插得上手的!(噢,比動感地帶還好。)
那麼我們怎麼來干預控件元素的分析呢?
1、ParseChildrenAttribute
2、ControlBuilderAttribute
ParseChildren用來指定控件的分析邏輯,它有bool一個參數,true表示控件標簽中的內容解釋為屬性,解析器用一組內定的控件生器來解析嵌套的屬性、子屬性、模板、集合屬性。你還可以用ParseChildren(true,"PropertyName")來指定嵌套內容傳入哪個屬性,WebControl內已經聲明為true。那麼如果為false,怎麼分析呢?在這種情況下,解析器用與控件相關的ControlBuilder來解釋控件開始和結標簽的內容,為將裡面的內容解釋為對象,文本也會解釋為LiteralControls,然後通過控件的AddParsedSubObject方法添加到控件中Controls中。
好,回過頭來看ListItem,ListItem不是從WebControl繼承而來,同時,它也沒有聲明為ParseChildren(true),那麼它是怎麼實現自己的分析邏輯的呢?答案就是它使用了ControlBuilderAttribute
[ControlBuilder(typeof(ListItemControlBuilder)), ]
public sealed class ListItem : IStateManager, IParserAccessor, IAttributeAccessor
{
}
再來看ListItemControlBuilder類
public class ListItemControlBuilder : ControlBuilder
{
public ListItemControlBuilder()
{
}
public override bool AllowWhitespaceLiterals()
{
return false;//除去控件標簽對嵌套內容首尾空白
}
public override bool HtmlDecodeLiterals()
{
return true;//刪除HTML編碼
}
}
這裡,我們可以不用ControlBuilder來使標簽中禁用HTML編碼,我們可以重載一個從WebControl繼承下的控件的AddParsedSubObject方法
protected override void AddParsedSubObject(object obj) {
if (obj is LiteralControl) {
Text = ((LiteralControl)obj).Text;
}
else {
throw new ArgumentException(
"The inner content must contain static text ");
}
// do anything you want.
}
請注意,這種做法,效率是不如ControlBuilder方法的,因為它會在每次請求實現邏輯時都執行一次,而前者只在代碼產生前的解析期被執行一次。
另外,比WebControl繼承下來的控件,要實現用ControlBuilder控制生成內容對象,要記得聲明ParseChilder(false)。