Asp.Net自定义控件设计时间问题

Asp.Net自定义控件设计时间问题,asp.net,custom-controls,web-controls,Asp.net,Custom Controls,Web Controls,我正在开发一组自定义控件,其中一个是“父控件”,任何其他控件都必须添加到此父控件的ITemplate属性中 但是在页面中,在设计时,我可以通过intellisense看到页面级别的其他控件,理论上我可以在任何地方添加它们 我想模拟asp:Table和asp:TableRow的行为,不能直接在asp:Table之外添加asp:TableRow 有没有办法做到这一点? 非常感谢 编辑:我已经部分解决了KP的建议,但如果你在评论中看到,这不是“真正”的解决方法(我认为)。 没人知道怎么做(我以前做过,

我正在开发一组自定义控件,其中一个是“父控件”,任何其他控件都必须添加到此父控件的ITemplate属性中

但是在页面中,在设计时,我可以通过intellisense看到页面级别的其他控件,理论上我可以在任何地方添加它们

我想模拟asp:Table和asp:TableRow的行为,不能直接在asp:Table之外添加asp:TableRow

有没有办法做到这一点? 非常感谢

编辑:我已经部分解决了KP的建议,但如果你在评论中看到,这不是“真正”的解决方法(我认为)。
没人知道怎么做(

我以前做过,但我没有可用的代码。我可以告诉您,我是通过使用内置ASP.NET Datagrid控件上的Reflector解决的。我能够对“包含”(“行”)和“容器”(“网格”)之间的关系进行反向工程。您必须使用属性以非常特定的方式将类排列在一起。

我根据我们的讨论编辑了整个答案。这是一个有效且经过测试的示例。我们有以下两个控件-
ParentControl
ChildControl
ParentControl
通过Intellisense可见,其中
ChildControl
仅作为
ParentControl
的子级可见。出于简单渲染目的,子级渲染为li标记并输出其“text”属性。父级控件确保在其自己的
RenderContents
事件期间要求每个子级渲染

子控件:

using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace TestControls
{
    [ToolboxItem(false), Bindable(false)]
    public class ChildControl : WebControl
    {
        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            base.Render(writer);

            //render the text property as a list item for example's sake
            writer.RenderBeginTag(HtmlTextWriterTag.Li);
            writer.Write(this.Text);
            writer.RenderEndTag();
        }

        [Browsable(true)]
        public string Text { get; set; }
    }
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace TestControls
{
    [ToolboxData("<{0}:ParentControl runat=\"server\"></{0}:ParentControl>")]
    [DefaultProperty("Children"), ParseChildren(true, "Children")]
    public class ParentControl : WebControl
    {
        private List<ChildControl> _children;

        protected override void RenderContents(HtmlTextWriter writer)
        {
            base.RenderContents(writer);

            //create a div, and write some sample text
            writer.RenderBeginTag(HtmlTextWriterTag.Div);
            writer.Write("Parent Control. Children:");

            //create a ul, and ask each child control to render
            writer.RenderBeginTag(HtmlTextWriterTag.Ul);

            foreach (ChildControl child in _children)
            {
                child.RenderControl(writer);
            }

            //close all tags
            writer.RenderEndTag();
            writer.RenderEndTag();
        }

        [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
        public virtual List<ChildControl> Children
        {
            get
            {
                if (_children == null)
                    _children = new List<ChildControl>();

                return _children;
            }
        }
    }
}
父控件:

using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace TestControls
{
    [ToolboxItem(false), Bindable(false)]
    public class ChildControl : WebControl
    {
        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            base.Render(writer);

            //render the text property as a list item for example's sake
            writer.RenderBeginTag(HtmlTextWriterTag.Li);
            writer.Write(this.Text);
            writer.RenderEndTag();
        }

        [Browsable(true)]
        public string Text { get; set; }
    }
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace TestControls
{
    [ToolboxData("<{0}:ParentControl runat=\"server\"></{0}:ParentControl>")]
    [DefaultProperty("Children"), ParseChildren(true, "Children")]
    public class ParentControl : WebControl
    {
        private List<ChildControl> _children;

        protected override void RenderContents(HtmlTextWriter writer)
        {
            base.RenderContents(writer);

            //create a div, and write some sample text
            writer.RenderBeginTag(HtmlTextWriterTag.Div);
            writer.Write("Parent Control. Children:");

            //create a ul, and ask each child control to render
            writer.RenderBeginTag(HtmlTextWriterTag.Ul);

            foreach (ChildControl child in _children)
            {
                child.RenderControl(writer);
            }

            //close all tags
            writer.RenderEndTag();
            writer.RenderEndTag();
        }

        [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
        public virtual List<ChildControl> Children
        {
            get
            {
                if (_children == null)
                    _children = new List<ChildControl>();

                return _children;
            }
        }
    }
}
还有,这里有一个,我按照它创建了上面的


我希望这会有所帮助。您仍然需要以您认为适合您的特定控件的方式处理子控件级别的渲染,但是以上内容可以帮助您开始,并且确实满足Intellisense模型的工作需要。

我在子控件中添加了[ToolboxItem(false)],然后我用属性[PersistenceMode(PersistenceMode.InnerProperty)]将其公开为父控件的属性。我认为它不是“正确的”这样做的方法,但目前是唯一一个做到这一点的方法…为什么这是“不正确”的方法?我相信你在正确的轨道上。另一个使用相同属性的例子:因为这样我的子控件不会自动渲染自己,这是父控件的一个简单属性,我必须在父级实现渲染逻辑…hone首先,我不明白asp:TableRow和asp:Table是如何工作的,我在reflector中看到了它们的代码,但我没有找到让TableRow在表外不可见的原因…@tanathos-这很公平。我编辑了答案,并提供了一个很好的链接,其中描述了intellisense是如何生成的。ToolboxItem看起来是您需要的唯一属性将控件隐藏在标记的顶级可见性之外。是的,它似乎涉及ToolBoxItem。如果我将其设置为false,则子控件不会出现在intellisense上(根本不会),但控件可以工作,它在html上呈现,即使VS无法识别标记。但我尝试了各种组合,我无法使它仅显示在父控件上…似乎什么都没有或全部…最后,我认为现在我将实现基于属性的呈现系统。无论如何,感谢您花时间帮助我!
* Hello World from Child 1
* Hello World from Child 2