简体   繁体   English

自定义ASP.NET容器控件

[英]Custom ASP.NET Container Control

I've been trying to create a custom control that works exactly like the Panel control except surrounded by a few divs and such to create a rounded box look. 我一直在尝试创建一个自定义控件,该控件的功能与Panel控件完全相同,只是被几个div包围,从而创建了一个圆形框外观。 I haven't been able to find a decent example of how to do this. 我还没有找到如何做到这一点的好例子。

I need to be able to place text and controls inside the control and access it directly without referencing the panel (exactly the way the Panel control works). 我需要能够在控件内部放置文本和控件并直接访问它,而无需引用面板(正是Panel控件的工作方式)。

Does anyone have any examples of this? 有人有这个例子吗?

There is two ways to do this. 有两种方法可以做到这一点。 One is to implement INamingContainer on your control, and it takes a lot of effort. 一种是在您的控件上实现INamingContainer,这需要很多工作。

The other way is to inherit from Panel, and override the RenderBeginTag and RenderEndTag methods to add your custom markup. 另一种方法是从Panel继承,并重写RenderBeginTag和RenderEndTag方法以添加自定义标记。 This is easy. 这很容易。

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");                     
    }
}

There are already quite a few answers here, but I just wanted to paste the most basic implementation of this without inheriting from Panel class. 这里已经有很多答案,但是我只想粘贴此方法的最基本实现,而不继承Panel类。 So here it goes: 所以就这样:

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);
    }
}

Then you can use it like this: 然后,您可以像这样使用它:

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

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

And from codebehind you can do things like this: 从代码背后,您可以执行以下操作:

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

Create a class that inherits System.Web.UI.Control, and overrride the Render ( HtmlTextWriter ) method. 创建一个继承System.Web.UI.Control的类,并重写Render(HtmlTextWriter)方法。 In this method, render surrounding start tags, then render the children(RenderChildren), then render end tags. 在此方法中,先渲染周围的开始标签,然后再渲染子元素(RenderChildren),然后再渲染结束标签。

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

Rounded corners is typically achieved using CSS and corner images for the top left, top right, bottom left and bottom right corners. 通常使用CSS和左上角,右上角,左下角和右下角的角图像来实现圆角。 It could be done using 4 nested divs, acting as layers, each of them having one corner image as their background image. 可以使用4个嵌套的div作为图层来完成,每个div都有一个角图像作为背景图像。

If you don't want to inherit directly from WebControl instead of from Panel, the easiest way to do this is to decorate the class with the attribute [ParseChildren(false)] . 如果您不想直接从WebControl而不是从Panel继承,则最简单的方法是使用[ParseChildren(false)]属性装饰类。 Although at first glance this might suggest that you don't want to parse children, what the false actually indicates is that you don't want the children to be treated as properties. 尽管乍一看可能表明您不想解析子级,但false实际含义是您不希望将子级视为属性。 Instead, you want them to be treated as controls. 相反,您希望将它们视为控件。

By using this attribute, you get virtually all of the functionality out of the box: 通过使用此属性,您几乎可以立即使用所有功能:

[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>");
    }
}

This will allow you to add RoundedBox controls to your pages, and add children (either asp.net controls or raw html) that will be rendered inside your div. 这将允许您向页面添加RoundedBox控件,并添加将在div中呈现的子级(asp.net控件或原始html)。

Of course, css would be added to correctly style the roundedbox class. 当然,将添加CSS以正确设置roundedbox类的样式。

Code project have something that might interest you : Panel Curve Container - An ASP.NET Custom Control Nugget . 代码项目可能会让您感兴趣: 面板曲线容器-ASP.NET自定义控件块 I am sure you can play with the code and have the behavior and look you want. 我确信您可以使用该代码,并具有所需的行为和外观。

替代文字

I looked at this question because I wanted to produce a 2 column layout panel. 我看了这个问题,因为我想制作一个2列的布局面板。 (not quite but its a much simpler example of what I needed. I'm sharing the solution that I wound up using: (不完全是,但是它是我所需要的一个简单得多的示例。我正在分享我使用的解决方案:

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

The issue I still have is the intellisense does't work for in this scenario, it won't suggest the Left and Right Content tags. 我仍然遇到的问题是intellisense在这种情况下不起作用,它不会建议“左右内容”标签。

Just another thing you can use, there's a rounded corner extender in the ASP.Net ajax toolkit. 您可以使用的另一件事是,ASP.Net ajax工具包中有一个圆角扩展器

I know it's not exactly what you asked for, but you don't have to write any custom code. 我知道这并不是您所要的,但您不必编写任何自定义代码。

Hope that helps! 希望有帮助!

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();
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM