Asp.Net Custom Control设计时间问题

时间:2010-02-09 18:16:03

标签: asp.net custom-controls web-controls

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

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

我想模仿asp的行为:表和asp:TableRow,你不能直接在asp外面添加一个asp:TableRow:表...

有没有办法达到这个目标? 非常感谢!

编辑:我已经部分解决了KP建议,但是如果您阅读评论,那么这不是“真正的”方式(我认为)。 没人知道怎么做? :(

2 个答案:

答案 0 :(得分:2)

我根据我们的讨论编辑了整个答案。这是一个经过实践检验的例子。我们有两个控件 - ParentControlChildControl。通过智能感知可以看到ParentControl,其中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;
            }
        }
    }
}

在我的标记中,我通过命名空间注册了控件:

<%@ Register TagPrefix="test" Namespace="TestControls" %>

然后添加了一些标记:

<test:ParentControl ID="test" runat="server">
    <test:ChildControl ID="child" Text="Hello World from Child 1" runat="server" />
    <test:ChildControl ID="child2" Text="Hello World from Child 2" runat="server" />
</test:ParentControl>

在上面的标记中,Intellisense选择了外部父控件,但没有看到子控件。一旦光标位于父控件内,Intellisense就会根据需要选择ChildControl标记。

最终输出是:

  

家长控制。儿童:

* Hello World from Child 1
* Hello World from Child 2

另外,这是一个good article on how the whole intellisence creation works,我按照这个创建了上面的内容。

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

答案 1 :(得分:0)

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