Professional Web Applications Themes

How to create a designer that behaves like the ASP:PANEL - ASP.NET Building Controls

I am creating a custom server control where the user can add any content similar to an ASP:PANEL. The custom control wraps the content in some extra HTML above and below their content. I did not use a templated property as it forces the developer to write more code in order to access any controls they place within the template. I started by inheriting from System.Web.UI.WebControls.Panel, which I do not really want to do in the long run, and created a designer that inherited from System.Web.UI.Design.WebControls.PanelDesigner. The control works in the designer with the exception of not using the class ...

  1. #1

    Default How to create a designer that behaves like the ASP:PANEL

    I am creating a custom server control where the user can add any content
    similar to an ASP:PANEL. The custom control wraps the content in some extra
    HTML above and below their content. I did not use a templated property as
    it forces the developer to write more code in order to access any controls
    they place within the template.

    I started by inheriting from System.Web.UI.WebControls.Panel, which I do not
    really want to do in the long run, and created a designer that inherited
    from System.Web.UI.Design.WebControls.PanelDesigner. The control works in
    the designer with the exception of not using the class names for some
    reason.

    What I would like is the control inherit from System.Web.UI.Control and
    System.Web.UI.Design.ControlDesigner as I do not want all the extra baggage
    the Panel control has. I have the control working just fine in the runtime
    by just using in the Render() method and using this to render the child
    controls:

    foreach (Control control in this.Controls)
    control.RenderControl(output);

    However, I can not for the life of me figure out how to get child controls
    to display in the design view. What do I need to do in the
    GetDesignTimeHtml() method of the designer that I have inherited from
    ControlDesigner? Or is there another designer I should use?

    Thanks in advance. Here is sample code:

    //// SERVER CONTROL

    using System;
    using System.Web.UI;

    public class Section : System.Web.UI.Control // WebControls.Panel
    {
    private void RenderSpacer(HtmlTextWriter output)
    {
    output.AddAttribute(HtmlTextWriterAttribute.Nowrap , "true");
    output.RenderBeginTag(HtmlTextWriterTag.Td);

    output.AddAttribute(HtmlTextWriterAttribute.Src, "/images/spacer.gif");
    output.AddAttribute(HtmlTextWriterAttribute.Width, "6");
    output.AddAttribute(HtmlTextWriterAttribute.Height , "1");
    output.RenderBeginTag(HtmlTextWriterTag.Img);
    output.RenderEndTag(); // IMG

    output.RenderEndTag(); // TD
    }

    protected override void Render(HtmlTextWriter output)
    {
    output.AddAttribute(HtmlTextWriterAttribute.Class, "sectionTable");
    output.AddAttribute(HtmlTextWriterAttribute.Width, "100%");
    output.RenderBeginTag(HtmlTextWriterTag.Table);
    output.RenderBeginTag(HtmlTextWriterTag.Tr);

    // Left Spacer cell
    RenderSpacer(output);

    // Content cell
    output.AddAttribute(HtmlTextWriterAttribute.Class, "sectionContent");
    output.RenderBeginTag(HtmlTextWriterTag.Td);

    foreach (Control control in this.Controls)
    control.RenderControl(output);

    output.RenderEndTag(); // TD

    // Right Spacer cell
    RenderSpacer(output);

    output.RenderEndTag(); // TR
    output.RenderEndTag(); // TABLE
    }
    }



    //// DESIGNER

    using System;
    using System.Text;

    public class SectionDesigner : System.Web.UI.Design.ControlDesigner //
    WebControls.PanelDesigner
    {
    private string RenderSpacer()
    {
    StringBuilder html = new StringBuilder();

    html.Append("<TD nowrap>");
    html.Append("<IMG src=\"/images/spacer.gif\" width=\"6\" height=\"1\">");
    html.Append("</TD>\n");

    return(html.ToString());
    }

    public override string GetDesignTimeHtml()
    {
    StringBuilder html = new StringBuilder();

    try
    {
    Section control = (Section)this.Component;

    html.Append("<TABLE class=\"sectionTable\" width=\"100%\">");
    html.Append("<TR>\n");

    // Left Spacer cell
    html.Append(RenderSpacer());

    html.Append("<TD class=\"sectionContent\" width=\"100%\">");
    //
    //This is where the child controls should be rendered
    //
    html.Append("</TD>\n");

    // Right Spacer cell
    html.Append(RenderSpacer());

    html.Append("</TR>");
    html.Append("</TABLE>");
    }
    catch (Exception ex)
    {
    html.Append(base.GetErrorDesignTimeHtml(ex));
    }

    if ((html == null) || (html.Length == 0))
    html.Append(GetEmptyDesignTimeHtml());

    return(html.ToString());
    }


    protected override string GetEmptyDesignTimeHtml()
    {
    return(base.GetEmptyDesignTimeHtml());
    }
    }



    //// WEBPAGE

    <BAXWEBUI:SECTION id="scMySection" runat="server">
    <ASP:LABEL id="lblSection" runat="server" text="My Label" /><BR>
    <ASP:PANEL id="pnlButtons" runat="server">
    <ASP:LINKBUTTON id="cmdBack" runat="server" text="Back"
    cssclass="buttonLeft" />
    <ASP:LINKBUTTON id="cmdSubmit" runat="server" text="Submit"
    cssclass="button" />
    <ASP:LINKBUTTON id="cmdReset" runat="server" text="Reset"
    cssclass="buttonRight" />
    </ASP:PANEL>
    </BAXWEBUI:SECTION>


    Cameron Eckman Guest

  2. #2

    Default Re: How to create a designer that behaves like the ASP:PANEL

    On Tue, 02 Aug 2005 11:38:13 -0700, Cameron Eckman wrote:
    > I am creating a custom server control where the user can add any content
    > similar to an ASP:PANEL. The custom control wraps the content in some extra
    > HTML above and below their content. I did not use a templated property as
    > it forces the developer to write more code in order to access any controls
    > they place within the template.
    >
    > I started by inheriting from System.Web.UI.WebControls.Panel, which I do not
    > really want to do in the long run, and created a designer that inherited
    > from System.Web.UI.Design.WebControls.PanelDesigner. The control works in
    > the designer with the exception of not using the class names for some
    > reason.
    >
    > What I would like is the control inherit from System.Web.UI.Control and
    > System.Web.UI.Design.ControlDesigner as I do not want all the extra baggage
    > the Panel control has. I have the control working just fine in the runtime
    > by just using in the Render() method and using this to render the child
    > controls:
    >
    > foreach (Control control in this.Controls)
    > control.RenderControl(output);
    >
    > However, I can not for the life of me figure out how to get child controls
    > to display in the design view. What do I need to do in the
    > GetDesignTimeHtml() method of the designer that I have inherited from
    > ControlDesigner? Or is there another designer I should use?
    >
    > Thanks in advance. Here is sample code:
    >
    > //// SERVER CONTROL
    >
    > using System;
    > using System.Web.UI;
    >
    > public class Section : System.Web.UI.Control // WebControls.Panel
    > {
    > private void RenderSpacer(HtmlTextWriter output)
    > {
    > output.AddAttribute(HtmlTextWriterAttribute.Nowrap , "true");
    > output.RenderBeginTag(HtmlTextWriterTag.Td);
    >
    > output.AddAttribute(HtmlTextWriterAttribute.Src, "/images/spacer.gif");
    > output.AddAttribute(HtmlTextWriterAttribute.Width, "6");
    > output.AddAttribute(HtmlTextWriterAttribute.Height , "1");
    > output.RenderBeginTag(HtmlTextWriterTag.Img);
    > output.RenderEndTag(); // IMG
    >
    > output.RenderEndTag(); // TD
    > }
    >
    > protected override void Render(HtmlTextWriter output)
    > {
    > output.AddAttribute(HtmlTextWriterAttribute.Class, "sectionTable");
    > output.AddAttribute(HtmlTextWriterAttribute.Width, "100%");
    > output.RenderBeginTag(HtmlTextWriterTag.Table);
    > output.RenderBeginTag(HtmlTextWriterTag.Tr);
    >
    > // Left Spacer cell
    > RenderSpacer(output);
    >
    > // Content cell
    > output.AddAttribute(HtmlTextWriterAttribute.Class, "sectionContent");
    > output.RenderBeginTag(HtmlTextWriterTag.Td);
    >
    > foreach (Control control in this.Controls)
    > control.RenderControl(output);
    >
    > output.RenderEndTag(); // TD
    >
    > // Right Spacer cell
    > RenderSpacer(output);
    >
    > output.RenderEndTag(); // TR
    > output.RenderEndTag(); // TABLE
    > }
    > }
    >
    >
    >
    > //// DESIGNER
    >
    > using System;
    > using System.Text;
    >
    > public class SectionDesigner : System.Web.UI.Design.ControlDesigner //
    > WebControls.PanelDesigner
    > {
    > private string RenderSpacer()
    > {
    > StringBuilder html = new StringBuilder();
    >
    > html.Append("<TD nowrap>");
    > html.Append("<IMG src=\"/images/spacer.gif\" width=\"6\" height=\"1\">");
    > html.Append("</TD>\n");
    >
    > return(html.ToString());
    > }
    >
    > public override string GetDesignTimeHtml()
    > {
    > StringBuilder html = new StringBuilder();
    >
    > try
    > {
    > Section control = (Section)this.Component;
    >
    > html.Append("<TABLE class=\"sectionTable\" width=\"100%\">");
    > html.Append("<TR>\n");
    >
    > // Left Spacer cell
    > html.Append(RenderSpacer());
    >
    > html.Append("<TD class=\"sectionContent\" width=\"100%\">");
    > //
    > //This is where the child controls should be rendered
    > //
    > html.Append("</TD>\n");
    >
    > // Right Spacer cell
    > html.Append(RenderSpacer());
    >
    > html.Append("</TR>");
    > html.Append("</TABLE>");
    > }
    > catch (Exception ex)
    > {
    > html.Append(base.GetErrorDesignTimeHtml(ex));
    > }
    >
    > if ((html == null) || (html.Length == 0))
    > html.Append(GetEmptyDesignTimeHtml());
    >
    > return(html.ToString());
    > }
    >
    >
    > protected override string GetEmptyDesignTimeHtml()
    > {
    > return(base.GetEmptyDesignTimeHtml());
    > }
    > }
    >
    >
    >
    > //// WEBPAGE
    >
    > <BAXWEBUI:SECTION id="scMySection" runat="server">
    > <ASP:LABEL id="lblSection" runat="server" text="My Label" /><BR>
    > <ASP:PANEL id="pnlButtons" runat="server">
    > <ASP:LINKBUTTON id="cmdBack" runat="server" text="Back"
    > cssclass="buttonLeft" />
    > <ASP:LINKBUTTON id="cmdSubmit" runat="server" text="Submit"
    > cssclass="button" />
    > <ASP:LINKBUTTON id="cmdReset" runat="server" text="Reset"
    > cssclass="buttonRight" />
    > </ASP:PANEL>
    > </BAXWEBUI:SECTION>
    Is it perhaps that you are missing ToolBoxData information provided to the
    class via the ToolBoxDataAttribute class?

    intrader Guest

  3. #3

    Default RE: How to create a designer that behaves like the ASP:PANEL

    Hi Cameron - and anyone else that could help on this :)

    This is exactly the same thing I want to do. I want that my coders drag my
    control to the design pane, have a panel with a "title" control already set,
    so they can add their own controls below the title.

    There are several things to note when creating this kind of control.
    - They must inherit INamingContainer

    - Call EnsureChildControls() in the end of your OnInit() and everytime you
    need to access one of your inner controls (like in accessor methods);

    - inside CreateChildControls(), you must follow these steps:
    1. Create a new instance of your inner control, like this:
    lblTitle= new Label();

    2. Add the control to the container Controls collection:
    this.Controls.Add(lblTitle);

    [3. Give it an ID. I had to make this manually as I have some validation
    controls being created and they need the ControlToValidate property set. Be
    sure to follow the rule ContainerID + InnerCtrlID when setting IDs here. As
    the brackets tell you, this step is optional :) ]
    lblTitle.ID = this.ID + "lblTitle";

    4. Set control properties. Here you show values of properties of your
    control in their places. In my case, I have the Title property, wich I want
    to show in my label:
    lblTitle.Text = "Section title";

    - Designer class - really needed?
    I am not sure if the designer is needed, as we are inheriting from Panel,
    that already has its own designer. Besides that, the inner controls, which
    are in Controls collection, are already rendered in this function call
    sequence:
    ControlDesigner.GetDesignTimeHtml()
    Control.RenderControl()
    Control.Render()
    Control.RenderChildren()

    In runtime, the title renders perfectly. But in design time, I cannot show
    my inner title. My design time should reflect the design time as much as
    possible. Does anyone knows how to do it?

    In other words, I would like to provide a control with predefined inner
    controls, where the coder using it can add and remove the contents at will. I
    want to automatically add some preset controls inside a panel and increase
    development speed. Is that THAT hard? :D

    If I use a designer inherited from ControlDesigner instead of
    ReadWriteControlDesigner (base of PanelDesigner), the inner controls work
    fine, but as you might already guessed, ControlDesigner is read-only, and
    does not allow other controls to be dropped inside of it.

    Other minor issues:
    - how to not allow some controls to be changed or deleted (like the panel
    title)?
    - do we really need 2 VisualStudios open to debug design time behavior?

    Maybe we can exchange more knowledge thru MSN Messenger; My address is
    lucianoluke at bol.com.br

    And if we can solve our problems, I promise that I will post an article in
    CodeProject explaining this, plus a link to the article here :)

    I would like to thank Lutz Roeder also, for his awesome .NET Reflector tool
    that was an invaluable help in understanding the inners of WebControls in
    ASP.NET.

    Hope we find an answer soon,
    Luciano Bargmann
    ----------------------------------------------------------------

    "Cameron Eckman" wrote:
    > I am creating a custom server control where the user can add any content
    > similar to an ASP:PANEL. The custom control wraps the content in some extra
    > HTML above and below their content. I did not use a templated property as
    > it forces the developer to write more code in order to access any controls
    > they place within the template.
    >
    > I started by inheriting from System.Web.UI.WebControls.Panel, which I do not
    > really want to do in the long run, and created a designer that inherited
    > from System.Web.UI.Design.WebControls.PanelDesigner. The control works in
    > the designer with the exception of not using the class names for some
    > reason.
    >
    > What I would like is the control inherit from System.Web.UI.Control and
    > System.Web.UI.Design.ControlDesigner as I do not want all the extra baggage
    > the Panel control has. I have the control working just fine in the runtime
    > by just using in the Render() method and using this to render the child
    > controls:
    >
    > foreach (Control control in this.Controls)
    > control.RenderControl(output);
    >
    > However, I can not for the life of me figure out how to get child controls
    > to display in the design view. What do I need to do in the
    > GetDesignTimeHtml() method of the designer that I have inherited from
    > ControlDesigner? Or is there another designer I should use?
    >
    > Thanks in advance. Here is sample code:
    >
    > //// SERVER CONTROL
    >
    > using System;
    > using System.Web.UI;
    >
    > public class Section : System.Web.UI.Control // WebControls.Panel
    > {
    > private void RenderSpacer(HtmlTextWriter output)
    > {
    > output.AddAttribute(HtmlTextWriterAttribute.Nowrap , "true");
    > output.RenderBeginTag(HtmlTextWriterTag.Td);
    >
    > output.AddAttribute(HtmlTextWriterAttribute.Src, "/images/spacer.gif");
    > output.AddAttribute(HtmlTextWriterAttribute.Width, "6");
    > output.AddAttribute(HtmlTextWriterAttribute.Height , "1");
    > output.RenderBeginTag(HtmlTextWriterTag.Img);
    > output.RenderEndTag(); // IMG
    >
    > output.RenderEndTag(); // TD
    > }
    >
    > protected override void Render(HtmlTextWriter output)
    > {
    > output.AddAttribute(HtmlTextWriterAttribute.Class, "sectionTable");
    > output.AddAttribute(HtmlTextWriterAttribute.Width, "100%");
    > output.RenderBeginTag(HtmlTextWriterTag.Table);
    > output.RenderBeginTag(HtmlTextWriterTag.Tr);
    >
    > // Left Spacer cell
    > RenderSpacer(output);
    >
    > // Content cell
    > output.AddAttribute(HtmlTextWriterAttribute.Class, "sectionContent");
    > output.RenderBeginTag(HtmlTextWriterTag.Td);
    >
    > foreach (Control control in this.Controls)
    > control.RenderControl(output);
    >
    > output.RenderEndTag(); // TD
    >
    > // Right Spacer cell
    > RenderSpacer(output);
    >
    > output.RenderEndTag(); // TR
    > output.RenderEndTag(); // TABLE
    > }
    > }
    >
    >
    >
    > //// DESIGNER
    >
    > using System;
    > using System.Text;
    >
    > public class SectionDesigner : System.Web.UI.Design.ControlDesigner //
    > WebControls.PanelDesigner
    > {
    > private string RenderSpacer()
    > {
    > StringBuilder html = new StringBuilder();
    >
    > html.Append("<TD nowrap>");
    > html.Append("<IMG src=\"/images/spacer.gif\" width=\"6\" height=\"1\">");
    > html.Append("</TD>\n");
    >
    > return(html.ToString());
    > }
    >
    > public override string GetDesignTimeHtml()
    > {
    > StringBuilder html = new StringBuilder();
    >
    > try
    > {
    > Section control = (Section)this.Component;
    >
    > html.Append("<TABLE class=\"sectionTable\" width=\"100%\">");
    > html.Append("<TR>\n");
    >
    > // Left Spacer cell
    > html.Append(RenderSpacer());
    >
    > html.Append("<TD class=\"sectionContent\" width=\"100%\">");
    > //
    > //This is where the child controls should be rendered
    > //
    > html.Append("</TD>\n");
    >
    > // Right Spacer cell
    > html.Append(RenderSpacer());
    >
    > html.Append("</TR>");
    > html.Append("</TABLE>");
    > }
    > catch (Exception ex)
    > {
    > html.Append(base.GetErrorDesignTimeHtml(ex));
    > }
    >
    > if ((html == null) || (html.Length == 0))
    > html.Append(GetEmptyDesignTimeHtml());
    >
    > return(html.ToString());
    > }
    >
    >
    > protected override string GetEmptyDesignTimeHtml()
    > {
    > return(base.GetEmptyDesignTimeHtml());
    > }
    > }
    >
    >
    >
    > //// WEBPAGE
    >
    > <BAXWEBUI:SECTION id="scMySection" runat="server">
    > <ASP:LABEL id="lblSection" runat="server" text="My Label" /><BR>
    > <ASP:PANEL id="pnlButtons" runat="server">
    > <ASP:LINKBUTTON id="cmdBack" runat="server" text="Back"
    > cssclass="buttonLeft" />
    > <ASP:LINKBUTTON id="cmdSubmit" runat="server" text="Submit"
    > cssclass="button" />
    > <ASP:LINKBUTTON id="cmdReset" runat="server" text="Reset"
    > cssclass="buttonRight" />
    > </ASP:PANEL>
    > </BAXWEBUI:SECTION>
    >
    >
    >
    Luciano Bargmann Guest

Similar Threads

  1. Replies: 0
    Last Post: March 29th, 11:28 PM
  2. Help, Contribute behaves strangly
    By Seven in forum Macromedia Contribute General Discussion
    Replies: 1
    Last Post: September 5th, 12:56 PM
  3. php script behaves different as cron job
    By Christoph in forum PHP Development
    Replies: 2
    Last Post: November 11th, 04:31 PM
  4. msinfo32 behaves differently under Windows XP
    By Ted in forum Windows XP/2000/ME
    Replies: 0
    Last Post: July 21st, 05:42 PM
  5. [Q] Window from Nib behaves oddly
    By Frederick Cheung in forum Mac Programming
    Replies: 0
    Last Post: July 18th, 03:56 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139