Reputation: 395
I give... after days trying to figure out what I'm missing I give up. I cannot figure out how to get my simple container control to properly display in the designer. Here is the basic markup of the custom control:
<div>
<div>Title</div>
<div>
<!-- ASP.Net child controls -->
</div>
</div>
Here is how it looks at runtime (title and then the child control is a GridView):
Here is the simple code for the basic container control:
namespace Shoe.Controls
{
//[Designer(typeof(ApplicationWindowDesigner))]
//[ParseChildren(false)]
//[PersistChildren(true)]
[ToolboxData("<{0}:ApplicationWindow runat=\"server\"></{0}:ApplicationWindow>")]
public class ApplicationWindow : System.Web.UI.WebControls.Panel
{
#region Designer Properties
[Category("Appearance")]
[DefaultValue("Application")]
[Description("Title that will appear at the top of the Window.")]
[Browsable(true)]
/*
public string Title
{
get{return (ViewState["ApplicationWindowTitle"] == null)?
string.Empty :
(string)ViewState["ApplicationWindowTitle"];}
set{ViewState["ApplicationWindowTitle"] = value;}
}
*/
public string Title {get; set;}
#endregion
#region Rending Methods
/*
protected override void Render(HtmlTextWriter writer)
{
this.EnsureChildControls();
writer.Write("<div class=\""+CssClass+"\" style=\"width: "+Width+"; height: "+Height+";\"><div>"+Title+"</div><div>");
RenderChildren(writer);
writer.Write("</div></div>");
}
*/
public override void RenderBeginTag(HtmlTextWriter writer)
{
writer.Write("<div class=\""+CssClass+"\" style=\"width: "+Width+"; height: "+Height+";\"><div>"+Title+"</div><div>");
//base.RenderBeginTag(writer);
}
public override void RenderEndTag(HtmlTextWriter writer)
{
//base.RenderEndTag(writer);
writer.Write("</div></div>");
}
#endregion
}
}
As you see the code above, it is currently based off of the Panel control. However, I have also tried just using WebControl as the base class and then providing my own designer as follows:
namespace Shoe.Controls
{
public class ApplicationWindowDesigner : ContainerControlDesigner
//public class ApplicationWindowDesigner : ControlDesigner
{
/*
public override void Initialize(IComponent component)
{
base.Initialize(component);
SetViewFlags(ViewFlags.DesignTimeHtmlRequiresLoadComplete, true);
}
public override string GetDesignTimeHtml()
{
//return base.GetDesignTimeHtml();
StringBuilder sb = new StringBuilder();
TextWriter s = new StringWriter(sb);
HtmlTextWriter h = new HtmlTextWriter(s);
ApplicationWindow app_wnd = (ApplicationWindow)this.Component;
app_wnd.RenderControl(h);
h.Dispose();
s.Dispose();
return sb.ToString();
}
*/
/*
public override string GetDesignTimeHtml(DesignerRegionCollection regions)
{
//return base.GetDesignTimeHtml(regions);
ApplicationWindow app_wnd = (ApplicationWindow)this.Component;
/
return GetDesignTimeHtml();
}
*/
}
}
As you can see, I've tried using ControlDesigner as the base class and ContainerControlDesigner as the base class. When I use the ControlDesigner I get the designer to properly render my title bar and divs; however it does not render the child controls (GridView). If I use ContainerControlDesigner it renders the child controls, but not the title bar and divs. I cannot figure out the magic combination that will give me a designer that renders my surrounding frame and the child controls.
Here is what it looks like in the designer when using the Panel as the base class for the control, no designer, and the Begin / End tag approach:
This is also what it looks like when I use WebControl as the base class for the control and use a designer based off of ContainerControlDesigner (child controld, but my title bar and divs are missing).
What am I missing? I've found several examples of ContainerControlDesigner but none of them really add anything to the surrounding control like I am.
Upvotes: 1
Views: 2300
Reputation: 402
Your on the right track... I do a similar thing for making rounded panels. Makes it tremendously easier just dropping in the panel and let the rendering create your surrounding divs. I'm able to drop child controls within and they render properly. Simply wrapping the base render methods.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.Design.WebControls;
using System.ComponentModel;
using System.ComponentModel.Design;
namespace MyExample
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:myPanel runat=server></{0}:bPanel>")]
[Designer(typeof(MyPanelDesigner))]
public class MyPanel : Panel
{
#region Property
private string _Title = "No Title Set";
public string Title
{
get { return _Title; }
set { _Title = value; }
}
#endregion
protected override void RenderChildren(HtmlTextWriter writer)
{
writer.Write(String.Format("<div><div>{0}</div></div>", this.Title));
base.RenderChildren(writer);
writer.Write("</div></div>");
}
}
public class MyPanelDesigner : PanelContainerDesigner
{
public override string GetDesignTimeHtml(System.Web.UI.Design.DesignerRegionCollection regions)
{
// Read Property off control
MyPanel c = (MyPanel)Component;
string sTitle = c.Title;
// Render design markup
StringBuilder sb = new StringBuilder();
sb.AppendFormat("<div><div>{0}</div></div>", sTitle);
sb.Append(base.GetDesignTimeHtml(regions));
sb.AppendFormat("</div></div>");
return sb.ToString();
}
}
}
Upvotes: 2