[英]ASP.NET WebControl ITemplate child controls are null
Here is what I want: 这是我想要的:
I want a control to put on a page, which other developers can place form elements inside of to display the entities that my control is searching. 我希望将控件放置在页面上,其他开发人员可以在页面上放置表单元素以显示控件正在搜索的实体。 I have the Searching logic all working. 我的搜索逻辑全部正常工作。 The control builds custom search fields and performs searches based on declarative C# classes implementing my SearchSpec
interface. 该控件构建自定义搜索字段,并基于实现我的SearchSpec
接口的声明性C#类执行搜索。
Here is what I've been trying: 这是我一直在尝试的方法:
I've tried using ITemplate on a WebControl which implements INamingContainer I've tried implementing a CompositeControl 我试过在实现INamingContainer的WebControl上使用ITemplate我试过实现CompositeControl
The closest I can get to working is below. 下面是我能最接近的工作方式。
OK I have a custom WebControl 好的,我有一个自定义的WebControl
[
AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal),
AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal),
DefaultProperty("SearchSpecName"),
ParseChildren(true),
ToolboxData("<{0}:SearchPage runat=\"server\"> </{0}:SearchPage>")
]
public class SearchPage : WebControl, INamingContainer
{
[Browsable(false),
PersistenceMode(PersistenceMode.InnerProperty),
DefaultValue(typeof(ITemplate), ""),
Description("Form template"),
TemplateInstance(TemplateInstance.Single),
TemplateContainer(typeof(FormContainer))]
public ITemplate FormTemplate { get; set; }
public class FormContainer : Control, INamingContainer{ }
public Control MyTemplateContainer { get; private set; }
[Bindable(true), Category("Behavior"), DefaultValue(""),
Description("The class name of the SearchSpec to use."), Localizable(false)]
public virtual string SearchSpecName
{
get;
set;
}
[Bindable(true), Category("Behavior"), DefaultValue(true),
Description("True if this is query mode."), Localizable(false)]
public virtual bool QueryMode
{
get;
set;
}
private SearchSpec _spec;
private SearchSpec Spec
{
get
{
if (_spec == null)
{
Type type = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.Name == SearchSpecName).First();
_spec = (SearchSpec)Assembly.GetExecutingAssembly().CreateInstance(type.Namespace + "." + type.Name);
}
return _spec;
}
}
protected override void CreateChildControls()
{
if (FormTemplate != null)
{
MyTemplateContainer = new FormTemplateContainer(this);
FormTemplate.InstantiateIn(MyTemplateContainer);
Controls.Add(MyTemplateContainer);
}
else
{
Controls.Add(new LiteralControl("blah"));
}
}
protected override void RenderContents(HtmlTextWriter writer)
{
// <snip>
}
protected override HtmlTextWriterTag TagKey
{
get
{
return HtmlTextWriterTag.Div;
}
}
}
public class FormTemplateContainer : Control, INamingContainer
{
private SearchPage parent;
public FormTemplateContainer(SearchPage parent)
{
this.parent = parent;
}
}
then the usage: 然后的用法:
<tster:SearchPage ID="sp1" runat="server" SearchSpecName="TestSearchSpec" QueryMode="False">
<FormTemplate>
<br />
Test Name:
<asp:TextBox ID="testNameBox" runat="server" Width="432px"></asp:TextBox>
<br />
Owner:
<asp:TextBox ID="ownerBox" runat="server" Width="427px"></asp:TextBox>
<br />
Description:
<asp:TextBox ID="descriptionBox" runat="server" Height="123px" Width="432px"
TextMode="MultiLine" Wrap="true"></asp:TextBox>
</FormTemplate>
</tster:SearchPage>
The problem is that in the CodeBehind, the page has members descriptionBox, ownerBox and testNameBox. 问题是在CodeBehind中,页面具有成员descriptionBox,ownerBox和testNameBox。 However, they are all null. 但是,它们全为空。 Furthermore, FindControl("ownerBox")
returns null as does this.sp1.FindControl("ownerBox")
. 此外, FindControl("ownerBox")
返回null,与this.sp1.FindControl("ownerBox")
。 I have to do this.sp1.MyTemplateContainer.FindControl("ownerBox")
to get the control. 我必须执行this.sp1.MyTemplateContainer.FindControl("ownerBox")
才能获得控件。
How can I make it so that the C# Code Behind will have the controls generated and not null in my Page_Load event so that developers can just do this: 我该如何做,以便后面的C#代码将生成控件,而在我的Page_Load事件中不为null,以便开发人员可以执行以下操作:
testNameBox.Text = "foo";
ownerBox.Text = "bar";
descriptionBox.Text = "baz";
好的,我通过使SearchPage扩展Panel并删除ParseChildren(true)来解决此问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.