我想像Panel
一样创建一个控件。
我希望我的控件接受一些控件作为孩子,而不输入模板名称,就像Panel
一样,如下所示:
<asp:Panel runat="server">
My content
<div>Content</div>
</asp:Panel>
我有内容控件,但没有告诉ITemplate
。
我基本上想转换这个
<my:MyControl runat="server">
<ContentTemplate>
My content
<div>Content</div>
</ContentTemplate>
</my:MyControl>
进入这个
<my:MyControl runat="server">
My content
<div>Content</div>
</my:MyControl>
这就是我所拥有的:
public class MyControl : CompositeControl
{
[TemplateInstance(TemplateInstance.Single)]
public ITemplate Content { get; set; }
protected override void CreateChildControls()
{
base.CreateChildControls();
Content.InstantiateIn(this);
}
}
以上内容适用于控件内部的<Content></Content>
标记,但没有它不起作用。该属性根本没有做任何事情(我猜)。有什么遗漏?
我怎样才能实现它?任何提示? 为什么Panel
支持此功能?
答案 0 :(得分:7)
我正在从内存中写这个,但我相信答案很简单,就是用属性ParseChildrenAttribute和PersistChildrenAttribute来装饰你的控件类,你不需要像你提议的那样使用模板
ParseChildrenAttribute.ChildrenAsProperties指定解析器是否应将控件标记的嵌套内容视为属性。将此设置为false将使解析器不会尝试将标记映射到属性名称。
PersistChildrenAttribute将告诉解析器将嵌套内容视为控件,解析后的控件将作为子控件添加到自定义面板控件中。
您的控件的代码将如下所示:
[ParseChildren(false)]
[PersistChildren(true)]
public class MyControl : CompositeControl
{
public override void RenderBeginTag(HtmlTextWriter writer)
{
base.RenderBeginTag(writer); // TODO: Do something else here if needed
}
public override void RenderEndTag(HtmlTextWriter writer)
{
base.RenderEndTag(writer); // TODO: Do something else here if needed
}
}
作为参考,您可以启动.NET Reflector并查看Panel控件的实现。
答案 1 :(得分:4)
答案 2 :(得分:2)
Hey Bruno,答案与用户控件无关,就你想要嵌套控件的方式而言。
它实际上与模板和模板有关。这就是服务器控件如何能够嵌套在其中的特定控件。
这通常是在数据绑定控件中找到。
遗憾的是,答案并非微不足道,但您可以找到完整的教程here
答案 3 :(得分:1)
根据您需要执行的操作,您可以创建asp.net Panel控件的子类。
我创建了类似下面的内容来封装我想在每个面板上使用的常用HTML。 (PanelWidth是定义一些标准sizings的枚举。)
public class StyledPanel : System.Web.UI.WebControls.Panel
{
public PanelWidth PanelWidth { get; set; }
public override void RenderBeginTag(HtmlTextWriter writer) {
string containerClass = string.Format("panel-container-{0}", (int)PanelWidth);
writer.WriteLine("<div class=\"" + containerClass + "\"" + ">");
}
public override void RenderEndTag(HtmlTextWriter writer) {
writer.WriteLine("</div>");
}
}
请使用,例如
<uc:StyledPanel PanelWidth="Full" runat="server">
<div>Stuff</div>
</uc:StyledPanel>
答案 4 :(得分:1)
前两行使其有效:
[ParseChildren(false)]
[PersistChildren(true)]
[ToolboxData("<{0}:MyPanel runat=server>Panel</{0}:MyPanel>")]
public class MyPanel : WebControl
{
}
HTML:
<%@ Register Assembly="WebApplication3" Namespace="WebApplication3" TagPrefix="cc1" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<cc1:MyPanel ID="MyPanel1" runat="server">
<h2>
Welcome to ASP.NET!
</h2>
<p>
To learn more about ASP.NET visit <a href="http://www.asp.net" title="ASP.NET Website">
www.asp.net</a>.
</p>
<p>
You can also find <a href="http://go.microsoft.com/fwlink/?LinkID=152368&clcid=0x409"
title="MSDN ASP.NET Docs">documentation on ASP.NET at MSDN</a>.
</p>
</cc1:MyPanel>
</asp:Content>
答案 5 :(得分:0)
构建自定义用户控件,然后利用它来进一步扩展子控件。
http://www.akadia.com/services/dotnet_user_controls.html
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
namespace Akadia
{
namespace SubmitButton
{
// User Control which contain a text box for your
// name and a button that will fire an event.
public class SubmitButtonControl : System.Windows.Forms.UserControl
{
private System.Windows.Forms.TextBox txtName;
private System.Windows.Forms.Label lblName;
private System.Windows.Forms.Button btnSubmit;
private System.ComponentModel.Container components = null;
// Declare delegate for submit button clicked.
//
// Most action events (like the Click event) in Windows Forms
// use the EventHandler delegate and the EventArgs arguments.
// We will define our own delegate that does not specify parameters.
// Mostly, we really don't care what the conditions of the
// click event for the Submit button were, we just care that
// the Submit button was clicked.
public delegate void SubmitClickedHandler();
// Constructor public SubmitButtonControl()
{
// Create visual controls
InitializeComponent();
}
// Clean up any resources being used.
protected override void Dispose( bool disposing )
{
if( disposing )
{
if( components != null )
components.Dispose();
}
base.Dispose( disposing );
}
.....
.....
// Declare the event, which is associated with our
// delegate SubmitClickedHandler(). Add some attributes
// for the Visual C# control property.
[Category("Action")]
[Description("Fires when the Submit button is clicked.")]
public event SubmitClickedHandler SubmitClicked;
// Add a protected method called OnSubmitClicked().
// You may use this in child classes instead of adding
// event handlers.
protected virtual void OnSubmitClicked()
{
// If an event has no subscribers registerd, it will
// evaluate to null. The test checks that the value is not
// null, ensuring that there are subsribers before
// calling the event itself.
if (SubmitClicked != null)
{
SubmitClicked(); // Notify Subscribers
}
}
// Handler for Submit Button. Do some validation before
// calling the event.
private void btnSubmit_Click(object sender, System.EventArgs e)
{
if (txtName.Text.Length == 0)
{
MessageBox.Show("Please enter your name.");
}
else
{
OnSubmitClicked();
}
}
// Read / Write Property for the User Name. This Property
// will be visible in the containing application.
[Category("Appearance")]
[Description("Gets or sets the name in the text box")]
public string UserName
{
get { return txtName.Text; }
set { txtName.Text = value; }
}
}
}
}