[英]Child Control Initialization in Custom Composite in ASP.NET
我正在研究的一系列控件的一部分顯然涉及到我將它們中的一些混合在一起復合到復合材料中。 我很快就開始知道這需要考慮(這對我來說都是新的!):)
我基本上有一個StyledWindow
控件,它本質上是一個美化的Panel
,能夠做其他位(如添加邊框等)。
這是實例化其中的子控件的代碼。 到目前為止,似乎已經正常使用普通的靜態控件:
protected override void CreateChildControls()
{
_panel = new Panel();
if (_editable != null)
_editable.InstantiateIn(_panel);
_regions = new List<IAttributeAccessor>();
_regions.Add(_panel);
}
當我嘗試在其中嵌套更復雜的控件時,問題就出現了。 此控件使用對頁面的引用,因為它注入了JavaScript以使其更加快速和響應( RegisterClientScriptBlock
是我需要頁面引用的唯一原因)。
現在,這導致了“對象null”錯誤,但我將其本地化為render方法,當然這是嘗試針對[null] Page
對象調用該方法。
令我感到困惑的是,控件在獨立時工作得很好,但是當放在StyledWindow
,一切都變得非常糟糕!
所以,看起來我在StyledWindow
或ChildControl
遺漏了一些東西。 有任何想法嗎?
正如Brad Wilson非常正確地指出的那樣,您沒有看到控件被添加到Controls
集合中。 這就是_panel
的用途,這就是為我處理這個問題,然后基本上覆蓋Controls
(我從某個指南得到了這個):
Panel _panel; // Sub-Control to store the "Content".
public override ControlCollection Controls
{
get
{
EnsureChildControls();
return _panel.Controls;
}
}
我希望這有助於澄清事情。 道歉。
是的,我一直在玩控制器,在復合材料中放置一個,在外部放置一個。 然后,我在控件生命周期中獲得了事件主要事件的Page狀態,並將其呈現給頁面。
獨立工作正常,頁面按預期進行。 但是,嵌套在Composite中的那個是不同的。 它的OnLoad
事件根本沒有被解雇! 所以我猜Brad可能是正確的,因為我沒有正確設置控件層次結構,有人可以提供一些關於我缺少的建議嗎? Panel方法不夠嗎? (好吧,顯然不是嗎?!):D
謝謝你的幫助,謝謝:)
我沒有看到你在任何地方將控件添加到Controls集合中,這可以解釋為什么他們無法訪問Page(因為他們從未正式放在頁面上)。
我總是把JavaScript調用放在OnLoad函數上。 如下。
protected override void OnLoad(EventArgs e)
{
// Do something to get the script
string script = GetScript();
this.Page.ClientScript.RegisterClientScriptBlock(this.Page.GetType(), "SomeJavaScriptName", script);
// Could also use this function to determine if the script has been register. i.e. more than 1 of the controls exists
this.Page.ClientScript.IsClientScriptBlockRegistered("SomeJavaScriptName");
base.OnLoad(e);
}
如果您仍想進行渲染,那么您只需在響應中編寫腳本即可。 這就是RegisterScriptBlock所做的,它只是將腳本內聯在頁面上。
是的,我決心今天破解這個! 這是我的想法:
Panel
的使用有點像黑客,所以我應該刪除它並找出它是如何完成的。 MyCtl.Controls[0].Controls
來訪問添加到復合的控件。 所以,我搜索並點擊MSDN , 這個artcle 真的很有幫助(就像幾乎復制'n'粘貼,並解釋得很好 - MSDN傳統上不好的東西)。 太好了!
所以,我扯掉了Panel
的使用,並且幾乎跟着artcle並把它作為福音,在我去的時候記筆記。
這就是我現在擁有的:
例如,以下是模板化控件的ASPX標記:
<cc1:TemplatedControl ID="MyCtl" runat="server">
<Template>
<!-- Templated Content Goes Here -->
</Template>
</cc1:TemplatedControl>
public class DummyWebControl : WebControl
{
// Acts as the surrogate for the templated controls.
// This is essentially the "interface" for the templated data.
}
在TemplateControl.cs中......
ITemplate _template;
// Surrogate to hold the controls instantiated from
// within the template.
DummyWebControl _owner;
protected override void CreateChildControls()
{
// Note we are calling base.Controls here
// (you will see why in a min).
base.Controls.Clear();
_owner = new DummyWebControl();
// Load the Template Content
ITemplate template = _template;
if (template == null)
template = new StyledWindowDefaultTemplate();
template.InstantiateIn(_owner);
base.Controls.Add(_owner);
ChildControlsCreated = true;
}
然后,為了便於訪問[Surrogate]對象的控件:
(這就是為什么我們需要清除/添加到base.Controls)
public override ControlCollection Controls
{
get
{
EnsureChildControls();
return _owner.Controls;
}
}
這就是它,當你知道如何時很容易! :)
下一頁:設計時區支持!
是的,我玩了,我認為我的控件實例化有問題,因為Longhorn是對的,我應該能夠在OnLoad
上創建腳本引用(我不能),而Brad是正確的我需要確保通過添加到組合的Controls
集合來維護我的Controls
層次結構。
所以,我在這里有兩件事:
Controls
屬性訪問器以返回此Panel
的Controls集合,因為我不想去ctl.Controls[0].Controls[0]
來獲得我想要的實際控件。 我刪除了這個,但我需要對它進行排序。 Panel
添加到Controls
集合中, 我現在已經這樣做了。 那么,它現在有效,但是, 如何獲取復合的Controls
屬性以返回Panel
的項目,而不是Panel
本身?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.