【问题标题】:Custom ASP.NET Container Control自定义 ASP.NET 容器控件
【发布时间】:2010-09-23 07:21:17
【问题描述】:

我一直在尝试创建一个自定义控件,该控件的工作原理与 Panel 控件完全相同,只是被几个 div 包围,以创建圆角框外观。我还没有找到一个很好的例子来说明如何做到这一点。

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

有人有这方面的例子吗?

【问题讨论】:

    标签: asp.net custom-controls panel


    【解决方案1】:

    有两种方法可以做到这一点。一种是在你的控件上实现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");                     
        }
    }
    

    【讨论】:

    • 这可能是一个非常愚蠢的问题,但由于我不能将此代码放在典型的用户控件 (.ascx) 中,我应该把它放在哪里?我创建了一个类并将其放置在其中,但是我不知道如何将其添加到页面(拖动只会创建一个链接)
    • 发一个关于如何使用ASP.NET Server控件的问题,我可以回答,这个小评论框里放不下解释。
    • 感谢乔纳森,非常感谢您的帮助:stackoverflow.com/questions/306381/aspnet-custom-controls
    【解决方案2】:

    这里已经有不少答案了,但我只是想粘贴这个最基本的实现,而不是从 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";
    

    【讨论】:

    • 如果目标是拥有左内容和右内容,您将如何更改 SimpleContainer 类?你能简单地拥有 2 个 ITemplate 属性吗? ParseChildren 属性呢?
    • 太好了,这应该是公认的解决方案。还是投了赞成票。
    【解决方案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 来完成,它们充当图层,每个图层都有一个角图像作为背景图像。

    【讨论】:

      【解决方案4】:

      代码项目有一些你可能感兴趣的东西:Panel Curve Container - An ASP.NET Custom Control Nugget。我相信您可以使用代码并拥有您想要的行为和外观。

      【讨论】:

        【解决方案5】:

        如果您不想直接从 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 以正确设置圆角框类的样式。

        【讨论】:

          【解决方案6】:

          还有一个你可以使用的东西,在 ASP.Net ajax 工具包中有一个rounded corner extender

          我知道这并不完全符合您的要求,但您不必编写任何自定义代码。

          希望有帮助!

          【讨论】:

            【解决方案7】:

            我查看这个问题是因为我想制作一个 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
                {
                }
            }
            

            我仍然遇到的问题是智能感知在这种情况下不起作用,它不会建议左右内容标签。

            【讨论】:

              【解决方案8】:
              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();
                  }
              
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2010-09-23
                • 2011-06-15
                • 2011-03-17
                • 1970-01-01
                • 2011-12-20
                相关资源
                最近更新 更多