1

这是我想要的:

我想要一个控件放在页面上,其他开发人员可以在其中放置表单元素以显示我的控件正在搜索的实体。我的搜索逻辑都在工作。该控件构建自定义搜索字段并基于实现我的SearchSpec接口的声明性 C# 类执行搜索。

这是我一直在尝试的:

我尝试在实现 INamingContainer 的 WebControl 上使用 ITemplate 我尝试实现 CompositeControl

我最接近工作的地方如下。

好的,我有一个自定义 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;
    }
}

然后用法:

<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>

问题是在 CodeBehind 中,页面有成员 descriptionBox、ownerBox 和 testNameBox。但是,它们都是空的。此外,FindControl("ownerBox")返回 null 一样this.sp1.FindControl("ownerBox")。我必须做this.sp1.MyTemplateContainer.FindControl("ownerBox")才能获得控制权。

我怎样才能做到这一点,以便在我的 Page_Load 事件中生成控件而不是空的 C# 代码,以便开发人员可以这样做:

testNameBox.Text = "foo";
ownerBox.Text = "bar";
descriptionBox.Text = "baz";
4

1 回答 1

0

好的,我通过使 SearchPage 扩展面板并删除 ParseChildren(true) 来解决此问题。

于 2010-04-18T16:13:34.670 回答