我正在研究的一系列控件中的一部分显然涉及到将它们中的一些混合在一起进入复合材料。我很快就开始知道这需要考虑(这对我来说都是新的!):)
我基本上有一个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
感谢您的帮助,感谢:)
答案 0 :(得分:2)
我没有看到你在任何地方将控件添加到Controls集合,这可以解释为什么他们无法访问页面(因为他们从未正式放在页面上)。
答案 1 :(得分:1)
我总是把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所做的,它只是将脚本内联在页面上。
答案 2 :(得分:1)
是的,我决心今天破解这个!以下是我的想法:
Panel
有点像黑客,所以我应该删除它并找出它是如何完成的。MyCtl.Controls[0].Controls
之类的事情来访问添加到合成中的控件。所以,我搜索并点击MSDN,this 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;
}
}
这就是它,当你知道怎么做时很容易! :)
下一步:设计时区支持!
答案 3 :(得分:0)
是的,我玩了,我认为我的控件实例化有问题,因为Longhorn是对的,我应该能够在OnLoad
创建脚本引用(我不能)和Brad是正确的,我需要通过添加到复合的Controls
集合来确保我的Controls
层次结构。
所以,我在这里有两件事:
Controls
属性访问器以返回此Panel
的控件集合,因为我不想让ctl.Controls[0].Controls[0]
进入我想要的实际控件。 我删除了这个,但我需要对此进行排序。 Panel
添加到Controls
集合中,我现在已经这样做了。 所以,它现在有效,如何让复合的Controls
属性返回Panel
中的项目,而不是Panel
本身? 强>