2009-10-21 54 views
2

我正在寫一個從CompositeControl繼承的小型ASP.Net自定義控件。該控件只是一個包含兩個子面板的面板,每個子面板中都有一個標籤。呈現時,我在HTML源代碼中看到,我的自定義控件的第一個子控件獲取兩個id屬性 - 第一個是自定義控件本身的ID,第二個是我分配給第一個子控件的ID屬性。這是爲什麼發生?爲什麼我的ASP.Net自定義控件在我的第一個子控件上呈現兩個id屬性?

代碼:

[ToolboxData("<{0}:MessageBox runat=server></{0}:MessageBox>")] 
public class MessageBox : CompositeControl { 

    private Panel _MessageHeaderContainer = null; 
    private Label _MessageHeaderLabel = null; 
    private Panel _MessageDetailsContainer = null; 
    private Label _MessageDetailsLabel = null; 

    protected override HtmlTextWriterTag TagKey { 
     get { 
      return HtmlTextWriterTag.Div; 
     } 
    } 

    protected override void CreateChildControls() { 

     // Message header area. 
     _MessageHeaderContainer = new Panel(); 
     _MessageHeaderContainer.ID = "HeaderContainer"; 
     _MessageHeaderContainer.CssClass = "__MessageBox_Container"; 
     this.Controls.Add(_MessageHeaderContainer); 

     // Message header text. 
     _MessageHeaderLabel = new Label(); 
     _MessageHeaderLabel.ID = "HeaderLabel"; 
     _MessageHeaderLabel.Text = "[ Header ]"; 
     _MessageHeaderContainer.Controls.Add(_MessageHeaderLabel); 

     // Message details area. 
     _MessageDetailsContainer = new Panel(); 
     _MessageDetailsContainer.ID = "DetailsContainer"; 
     this.Controls.Add(_MessageDetailsContainer); 

     // Message details text. 
     _MessageDetailsLabel = new Label(); 
     _MessageDetailsLabel.ID = "DetailsLabel"; 
     _MessageDetailsLabel.Text = "[ Details ]"; 
     _MessageDetailsContainer.Controls.Add(_MessageDetailsLabel); 

    } 

    protected override void RenderContents(HtmlTextWriter output) { 
     AddAttributesToRender(output); 

     // Render the box. 
     _MessageHeaderContainer.RenderControl(output); 
     _MessageDetailsContainer.RenderControl(output); 
    } 
} 

用法在ASPX頁:

<cc:MessageBox ID="ctlMessageBox" runat="server" /> 

HTML輸出:

<div id="ctl00_ctl00_ctlMessageBox"> 
    <div id="ctl00_ctl00_ctlMessageBox" id="ctl00_ctl00_ctlMessageBox_HeaderContainer" class="__MessageBox_Container"> 
     <span id="ctl00_ctl00_ctlMessageBox_HeaderLabel">[ Header ]</span> 
    </div><div id="ctl00_ctl00_ctlMessageBox_DetailsContainer"> 
     <span id="ctl00_ctl00_ctlMessageBox_DetailsLabel">[ Details ]</span> 
    </div> 
</div> 
+0

它也好像我分配給控件本身的任何屬性(即this.CssClass =「xxxx」)被分配給控件的最外面的自動生成的div標記以及第一個子控件的呈現的div標記。 – 2009-10-21 14:14:51

+0

從Render函數中刪除AddAttributesToRender(output)行會停止將根標記的所有屬性添加到第一個子項。我不確定AddAttributesToRender函數的意義是什麼......任何人都可以啓發我爲什麼要調用這個函數? – 2009-10-21 14:46:35

+0

如果您想更多地控制自定義控件渲染的方式,您可以調用它。 它將應該分配給自定義控件(樣式等來自ASPX標記和其他來源)的屬性添加到呈現的下一個標記中。你不需要它,因爲你讓ASP.NET負責渲染。如果你重寫Render方法(就像我的例子),你會需要它。 – 2009-10-21 14:58:56

回答

4

您可以通過徹底消除了RenderContents方法解決這個問題 - 不要用任何東西取代它。默認情況下,複合控件呈現其所有子控件。如果你這樣做,你的控制產生乾淨的標記:

<div id="test"> 
    <div id="test_HeaderContainer" class="__MessageBox_Container"> 
    <span id="test_HeaderLabel">[ Header ]</span> 
    </div> 
    <div id="test_DetailsContainer"> 
    <span id="test_DetailsLabel">[ Details ]</span> 
    </div> 
</div> 

正如您所指出的那樣,AddAttributesToRender方法是罪魁禍首 - 這是一個方便的方法使頂層控件的所有屬性(當前上下文是否是或者不是)。你會這麼稱呼的唯一原因是,如果你自己完全控制了渲染過程,並想要在一個語句中渲染頂層控件的所有屬性。

+0

+1 - 謝謝!非常有幫助。 – 2009-10-21 14:47:08

-1

這是ID ASP.NET分配自定義控制作爲一個整體。如果將自定義控件包裝在Div或Span中(在自定義控件代碼本身中,而不是在標記中),則該ID將被分配給該自定義控件,而不是您的第一個內部「控件」。

事情是這樣的:

protected override void Render(HtmlTextWriter writer) 
{ 
    AddAttributesToRender(writer); 

    //must render tag or first inner control will get two IDs 
    writer.RenderBeginTag(HtmlTextWriterTag.Span); 

    //render child controls here... 

    writer.RenderEndTag(); 
} 
+0

我通過添加output.RenderBeginTag(HtmlTextWriterTag.Div)作爲評論「Render the box」下的第一行(並且在渲染子控件後添加了相應的output.RenderEndTag())。現在,HTML輸出包含一個封閉div標籤有一個重複的id作爲自定義控件自己的「root」div標籤。基本上我有

< child control stuff />
。我仍然在渲染輸出中有重複的控件ID - 不好。 – 2009-10-21 14:22:08

+1

嘗試重寫「Render」,而不是「RenderContents」。 ,嘗試刪除HtmlTextWriterTag TagKey – 2009-10-21 14:26:50

+0

我試着渲染一個跨度,沒有去 – sq33G 2011-12-15 10:01:19

相關問題