How to make control with children without declaring a template tag?

I want to create a control just like Panel .

I want my control to accept some controls as children without entering a template name, like Panel , as shown below:

 <asp:Panel runat="server"> My content <div>Content</div> </asp:Panel> 

I have controls with content inside without telling what ITemplate .

I basically want to convert this

 <my:MyControl runat="server"> <ContentTemplate> My content <div>Content</div> </ContentTemplate> </my:MyControl> 

In that

 <my:MyControl runat="server"> My content <div>Content</div> </my:MyControl> 

Here is what I have:

 public class MyControl : CompositeControl { [TemplateInstance(TemplateInstance.Single)] public ITemplate Content { get; set; } protected override void CreateChildControls() { base.CreateChildControls(); Content.InstantiateIn(this); } } 

Above works with <Content></Content> tags inside the control, but does not work without it. And the attribute does nothing (I think). What is missing?

How can i achieve this? Any hints? Why does Panel support this?

+6
c # controls controltemplate
source share
6 answers

I write this from memory, but I find the answer simple as beautifying your ParseChildrenAttribute and PersistChildrenAttribute attribute management class, and you don’t need to work with templates as you suggest.

ParseChildrenAttribute.ChildrenAsProperties indicates whether the parser should treat the embedded content of the control tag as properties. Setting this parameter to false will cause the parser not to try to match tags with property names.

The PersistChildrenAttribute function will tell the parser to treat the embedded content as controls, and the syntax controls will be added as child controls to the user panel control.

The code for your control will look something like this:

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

For reference, you can run .NET Reflector and look at the implementation of the Panel control.

+7
source share

Bruno, you are probably looking for this one . And also a similar answer here .

+4
source share

Hi Bruno, the answer is not related to user preferences in terms of how you want to set the controls.

In fact, this applies to templates and templates. The way server controls can have specific controls nested within them.

This is usually found in data controls.

The answer, unfortunately, is not trivial, but you can find the full tutorial here

UPDATE

Hmm ... I think where it just complicates the situation. What prevents you from creating a custom control, nested controls inside it, and then accessing this control through the ControlCollection property of your parent control?

+2
source share

Depending on what you need to do, you can simply subclass the asp.net Panel control.

I created something like the following to encapsulate the generic HTML code that I wanted in each of my own panels. (PanelWidth is an enumeration defining some standard values.)

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

Call it for example

 <uc:StyledPanel PanelWidth="Full" runat="server"> <div>Stuff</div> </uc:StyledPanel> 
+1
source share

The first two lines make it work:

 [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&amp;clcid=0x409" title="MSDN ASP.NET Docs">documentation on ASP.NET at MSDN</a>. </p> </cc1:MyPanel> </asp:Content> 
+1
source share

Create a custom user control, and then use it to further expand the child controls.

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; } } } } } 
0
source share

All Articles