自定义ASP.NET容器控件

时间:2008-11-20 18:11:17

标签: asp.net custom-controls panel

我一直在尝试创建一个自定义控件,其工作方式与Panel控件完全相同,除了包含几个div等,以创建圆角框外观。我还没有找到一个如何做到这一点的体面的例子。

我需要能够在控件内放置文本和控件并直接访问它而无需引用面板(与Panel控件的工作方式完全相同)。

有没有人有这方面的例子?

8 个答案:

答案 0 :(得分:15)

有两种方法可以做到这一点。一种是在你的控件上实现INamingContainer,这需要付出很多努力。

另一种方法是从Panel继承,并覆盖RenderBeginTag和RenderEndTag方法以添加自定义标记。这很容易。

public class RoundedCornersPanel : System.Web.UI.WebControls.Panel
{
    public override RenderBeginTag (HtmlTextWriter writer)
    {
        writer.Write("Your rounded corner opening markup");
        base.RenderBeginTag(writer);
    }

    public override RenderEndTag (HtmlTextWriter writer)
    {
        base.RenderEndTag(writer);
        writer.Write("Your rounded corner closing markup");                     
    }
}

答案 1 :(得分:13)

这里已经有了不少答案,但我只想粘贴最基本的实现而不继承Panel类。所以这就是:

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

[ToolboxData("<{0}:SimpleContainer runat=server></{0}:SimpleContainer>")]
[ParseChildren(true, "Content")]
public class SimpleContainer : WebControl, INamingContainer
{
    [PersistenceMode(PersistenceMode.InnerProperty)]
    [TemplateContainer(typeof(SimpleContainer))]
    [TemplateInstance(TemplateInstance.Single)]
    public virtual ITemplate Content { get; set; }

    public override void RenderBeginTag(HtmlTextWriter writer)
    {
        // Do not render anything.
    }

    public override void RenderEndTag(HtmlTextWriter writer)
    {
        // Do not render anything.
    }

    protected override void RenderContents(HtmlTextWriter output)
    {
        output.Write("<div class='container'>");
        this.RenderChildren(output);
        output.Write("</div>");
    }

    protected override void OnInit(System.EventArgs e)
    {
        base.OnInit(e);

        // Initialize all child controls.
        this.CreateChildControls();
        this.ChildControlsCreated = true;
    }

    protected override void CreateChildControls()
    {
        // Remove any controls
        this.Controls.Clear();

        // Add all content to a container.
        var container = new Control();
        this.Content.InstantiateIn(container);

        // Add container to the control collection.
        this.Controls.Add(container);
    }
}

然后你可以像这样使用它:

<MyControls:SimpleContainer
    ID="container1"
    runat="server">
    <Content>
        <asp:TextBox
            ID="txtName"
            runat="server" />

        <asp:Button
            ID="btnSubmit"
            runat="server"
            Text="Submit" />
    </Content>
</MyControls:SimpleContainer>

从代码隐藏中你可以做到这样的事情:

this.btnSubmit.Text = "Click me!";
this.txtName.Text = "Jack Sparrow";

答案 2 :(得分:3)

创建一个继承System.Web.UI.Control的类,并重写Render(HtmlTextWriter)方法。 在此方法中,渲染周围的开始标记,然后渲染子项(RenderChildren),然后渲染结束标记。

protected override void Render ( HtmlTextWriter output )
{
  output.Write ( "<div>" );
  RenderChildren ( output );
  output.Write ( "</div>" );
}

通常使用CSS和角落图像来实现圆角,左上角,右上角,左下角和右下角。 它可以使用4个嵌套的div来完成,作为图层,每个都有一个角图像作为背景图像。

答案 3 :(得分:2)

代码项目可能会让您感兴趣:Panel Curve Container - An ASP.NET Custom Control Nugget。我相信你可以玩代码并拥有你想要的行为。

alt text

答案 4 :(得分:2)

如果您不想直接从WebControl继承而不是从Panel继承,最简单的方法是使用属性[ParseChildren(false)]修饰类。虽然乍一看这可能表明你不想解析孩子,false实际上表明你不希望孩子被视为财产。相反,您希望将它们视为控件。

通过使用此属性,您几乎可以获得所有功能:

[ToolboxData("<{0}:RoundedBox runat=server></{0}:RoundedBox>")]
[ParseChildren(false)]
public class RoundedBox : WebControl, INamingContainer
{
    public override void RenderBeginTag(HtmlTextWriter writer)
    {
        writer.Write("<div class='roundedbox'>");
    }

    public override void RenderEndTag(HtmlTextWriter writer)
    {
        writer.Write("</div>");
    }
}

这将允许您将RoundedBox控件添加到您的页面,并添加将在div中呈现的子项(asp.net控件或原始html)。

当然,会添加css以正确设置圆形框类的样式。

答案 5 :(得分:0)

您可以使用另一件事,ASP.Net ajax工具包中有rounded corner extender

我知道这不是你要求的,但你不必编写任何自定义代码。

希望有所帮助!

答案 6 :(得分:0)

我看了这个问题,因为我想制作一个2列布局面板。 (不完全是,但它是我需要的一个更简单的例子。我正在分享我最终使用的解决方案:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Syn.Test
{
    [DefaultProperty("Text")]
    [ToolboxData("<{0}:MultiPanel runat=server></{0}:MultiPanel>")]
    [ParseChildren(true)]
    [PersistChildren(false)]
    public class MultiPanel : WebControl, INamingContainer
    {
        public ContentContainer LeftContent { get; set; }

        public ContentContainer RightContent { get; set; }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();
        }

        protected override void Render(HtmlTextWriter output)
        {
            output.AddStyleAttribute("width", "600px");
            output.RenderBeginTag(HtmlTextWriterTag.Div);

            output.AddStyleAttribute("float", "left");
            output.AddStyleAttribute("width", "280px");
            output.AddStyleAttribute("padding", "10px");
            output.RenderBeginTag(HtmlTextWriterTag.Div);
            LeftContent.RenderControl(output);
            output.RenderEndTag();

            output.AddStyleAttribute("float", "left");
            output.AddStyleAttribute("width", "280px");
            output.AddStyleAttribute("padding", "10px");
            output.RenderBeginTag(HtmlTextWriterTag.Div);
            RightContent.RenderControl(output);
            output.RenderEndTag();

            output.RenderEndTag();
         }
    }

    [ParseChildren(false)]
    public class ContentContainer : Control, INamingContainer
    {
    }
}

我仍然遇到的问题是intellisense在这种情况下不起作用,它不会建议使用Left和Right Content标签。

答案 7 :(得分:-1)

public class myCustomPanel : Panel
{
    public override void RenderBeginTag(HtmlTextWriter writer)
    {
        writer.AddAttribute(HtmlTextWriterAttribute.Class, "top_left_corner");
        writer.RenderBeginTag(HtmlTextWriterTag.Div);
            base.RenderBeginTag(writer);
    }

    public override void RenderEndTag(HtmlTextWriter writer)
    {
            base.RenderEndTag(writer);
        writer.RenderEndTag();
    }

}