我一直在尝试创建一个自定义控件,该控件的工作原理与 Panel 控件完全相同,只是被几个 div 包围,这样可以创建一个圆角框外观。我还没有找到一个很好的例子来说明如何做到这一点。
我需要能够在控件内放置文本和控件并直接访问它而不引用面板(正是面板控件的工作方式)。
有没有人有这方面的例子?
我一直在尝试创建一个自定义控件,该控件的工作原理与 Panel 控件完全相同,只是被几个 div 包围,这样可以创建一个圆角框外观。我还没有找到一个很好的例子来说明如何做到这一点。
我需要能够在控件内放置文本和控件并直接访问它而不引用面板(正是面板控件的工作方式)。
有没有人有这方面的例子?
有两种方法可以做到这一点。一种是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");
}
}
这里已经有很多答案了,但我只是想粘贴这个最基本的实现,而不是从 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";
创建一个继承 System.Web.UI.Control 的类,并重写 Render (HtmlTextWriter) 方法。在此方法中,渲染周围的开始标签,然后渲染子项(RenderChildren),然后渲染结束标签。
protected override void Render ( HtmlTextWriter output )
{
output.Write ( "<div>" );
RenderChildren ( output );
output.Write ( "</div>" );
}
圆角通常使用 CSS 和左上角、右上角、左下角和右下角的角图像来实现。可以使用 4 个嵌套的 div 来完成,它们充当图层,每个图层都有一个角图像作为背景图像。
代码项目有一些您可能感兴趣的东西:Panel Curve Container - An ASP.NET Custom Control Nugget。我相信您可以使用代码并拥有您想要的行为和外观。
如果您不想直接从 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 以正确设置 roundedbox 类的样式。
我看这个问题是因为我想制作一个 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
{
}
}
我仍然遇到的问题是智能感知在这种情况下不起作用,它不会建议左右内容标签。
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();
}
}