Adding Design-Time Support (Cont.) - Page 11
August 16, 2002
Adding a designer
As written, the Blog control will not have any visible interface
in the Design view of the Web Forms editor. This can make it more difficult to
select the control on the page, and also may make it more difficult to
understand what the control will look like at runtime. To correct this
problem, we can add support for a designer that will render HTML at design
time that approximates the look of the Blog control at runtime. Note that you
can also create designers that completely reproduce the runtime output of a
control, but doing so is more involved and beyond the scope of this book
All server control designers derive from the class System.Web.UI.Design.ControlDesigner, which exposes a
number of methods you can override to provide design-time rendering for your
control. Example
6-10 overrides the GetDesignTimeHtml method to return simple HTML. Note
that the example shows the entire designer class for the Blog control, which
you can add to the existing Blog.cs class file (making sure that the
class declaration is within the namespace curly
braces).
Example 6-10: BlogDesigner class public class BlogDesigner:ControlDesigner
{
public override string GetDesignTimeHtml( )
{
return "<h1>Blog</h2><hr/><hr/>";
}
}
To tie this designer into the Blog class, we use the Designer attribute, as shown in the following snippet.
Note that this code also adds a Description
attribute that describes what the control does. [
Description("Simple Blog control. Supports display of Web log / news
items from an XML file."),
Designer(typeof(aspnetian.BlogDesigner)),
ToolboxData("<{0}:Blog runat=server></{0}:Blog>")
]
public class Blog:Panel, INamingContainer
{ // class implementation }
As you can see, the BlogDesigner
class is extremely simple, but it adds a lot to the control's design-time
appearance on a web page, as shown in Figure
6-4.
Figure 6-4. Adding design-time rendering
|
|
Example
6-11 shows the code for the Blog control, updated with attributes to
enable design-time support for the control in Design view and the Property
browser. Note that the example adds several using
directives to import the namespaces needed to support the attributes and
designer classes we've used. The example also adds an enumeration to be used
for the value of the Mode property and a new property, SeparatorColor.
Example 6-11: Updated Blog.cs using System;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Design;
using System.IO;
using System.Web;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
[
assembly: TagPrefix("aspnetian", "aspnetian")
]
namespace aspnetian
{
public enum BlogMode
{
Add,
Display
}
[
Description(@"Simple Blog control. Supports display of Web log / news
items from an XML file."),
Designer(typeof(aspnetian.BlogDesigner)),
ToolboxData("<{0}:Blog runat=server></{0}:Blog>")
]
public class Blog:Panel, INamingContainer
{
protected DataSet BlogDS;
protected TextBox TitleTB;
protected TextBox BlogText;
private string _addRedirect;
private string _email;
private BlogMode _mode;
private Color _separatorColor = Color.Black;
[
Browsable(true),
Category("Behavior"),
Description("URL to which the page should redirect after
successful submission of a new Blog entry."),
Editor(typeof(System.Web.UI.Design.UrlEditor), typeof(UITypeEditor))
]
public string AddRedirect
{
get
{
return this._addRedirect;
}
set
{
this._addRedirect = value;
}
}
[
Browsable(true),
Category("Behavior"),
Description("Email address the control will use for listing in new
Blog entries.")
]
public string Email
{
get
{
return this._email;
}
set
{
this._email = value;
}
}
[
Browsable(true),
Category("Behavior"),
Description("Controls whether existing Blogs are displayed, or
fields for creating a new Blog entry.")
]
public BlogMode Mode
{
get
{
return this._mode;
}
set
{
this._mode = value;
}
}
[
Browsable(true),
Category("Appearance"),
Description("Controls the color of the line that separates Blog
entries when in display mode.")
]
public Color SeparatorColor
{
get
{
return this._separatorColor;
}
set
{
this._separatorColor = value;
}
}
protected override void OnInit(EventArgs e)
{
LoadData( );
base.OnInit(e);
}
protected override void CreateChildControls( )
{
if (this._mode != BlogMode.Add)
{
DisplayBlogs( );
}
else
{
NewBlog( );
}
}
protected void LoadData( )
{
BlogDS = new DataSet( );
try
{
BlogDS.ReadXml(Page.Server.MapPath("Blog.xml"));
}
catch (FileNotFoundException fnfEx)
{
CreateBlankFile( );
LoadData( );
}
}
protected void DisplayBlogs( )
{
DateTime BlogDate;
DateTime CurrentDate = new DateTime( );
DataRowCollection BlogRows = BlogDS.Tables[0].Rows;
foreach (DataRow BlogDR in BlogRows)
{
string BDate = BlogDR["date"].ToString( );
BlogDate = new DateTime(Convert.ToInt32(BDate.Substring(4, 4)),
Convert.ToInt32(BDate.Substring(0, 2)),
Convert.ToInt32(BDate.Substring(2, 2)));
if (CurrentDate != BlogDate)
{
Label Date = new Label( );
Date.Text = BlogDate.ToLongDateString( );
Date.Font.Size = FontUnit.Large;
Date.Font.Bold = true;
this.Controls.Add(Date);
this.Controls.Add(new LiteralControl("<br/><br/>"));
CurrentDate = BlogDate;
}
HtmlAnchor Anchor = new HtmlAnchor( );
Anchor.Name = "#" + BlogDR["anchorID"].ToString( );
this.Controls.Add(Anchor);
Label Title = new Label( );
Title.Text = BlogDR["title"].ToString( );
Title.Font.Size = FontUnit.Larger;
Title.Font.Bold = true;
this.Controls.Add(Title);
this.Controls.Add(new LiteralControl("<p>"));
LiteralControl BlogText = new LiteralControl("<div>" +
BlogDR["text"].ToString( ) + "</div>");
this.Controls.Add(BlogText);
this.Controls.Add(new LiteralControl("</p>"));
HyperLink Email = new HyperLink( );
Email.NavigateUrl = "mailto:" + BlogDR["email"].ToString( );
Email.Text = "E-mail me";
this.Controls.Add(Email);
this.Controls.Add(new LiteralControl(" | "));
HyperLink AnchorLink = new HyperLink( );
AnchorLink.NavigateUrl = Page.Request.Url.ToString( ) + "#" +
BlogDR["anchorID"].ToString( );
AnchorLink.Text = "Link";
this.Controls.Add(AnchorLink);
this.Controls.Add(new LiteralControl("<hr color='" +
_separatorColor.ToKnownColor( ) + "' width='100%'/><br/>"));
}
}
protected void NewBlog( )
{
Label Title = new Label( );
Title.Text = "Create New Blog";
Title.Font.Size = FontUnit.Larger;
Title.Font.Bold = true;
this.Controls.Add(Title);
this.Controls.Add(new LiteralControl("<br/><br/>"));
Label TitleLabel = new Label( );
TitleLabel.Text = "Title: ";
TitleLabel.Font.Bold = true;
this.Controls.Add(TitleLabel);
TitleTB = new TextBox( );
this.Controls.Add(TitleTB);
this.Controls.Add(new LiteralControl("<br/>"));
Label BlogTextLabel = new Label( );
BlogTextLabel.Text = "Text: ";
BlogTextLabel.Font.Bold = true;
this.Controls.Add(BlogTextLabel);
BlogText = new TextBox( );
BlogText.TextMode = TextBoxMode.MultiLine;
BlogText.Rows = 10;
BlogText.Columns = 40;
this.Controls.Add(BlogText);
this.Controls.Add(new LiteralControl("<br/>"));
Button Submit = new Button( );
Submit.Text = "Submit";
Submit.Click += new EventHandler(this.Submit_Click);
this.Controls.Add(Submit);
}
protected void Submit_Click(object sender, EventArgs e)
{
EnsureChildControls( );
AddBlog( );
}
protected void AddBlog( )
{
DataRow NewBlogDR;
NewBlogDR = BlogDS.Tables[0].NewRow( );
NewBlogDR["date"] = FormatDate(DateTime.Today);
NewBlogDR["title"] = TitleTB.Text;
NewBlogDR["text"] = BlogText.Text;
NewBlogDR["anchorID"] = Guid.NewGuid().ToString( );
NewBlogDR["email"] = _email;
BlogDS.Tables[0].Rows.InsertAt(NewBlogDR, 0);
BlogDS.WriteXml(Page.Server.MapPath("Blog.xml"));
Page.Response.Redirect(_addRedirect);
}
protected string FormatDate(DateTime dt)
{
string retString;
retString = String.Format("{0:D2}", dt.Month);
retString += String.Format("{0:D2}", dt.Day);
retString += String.Format("{0:D2}", dt.Year);
return retString;
}
public void CreateBlankFile( )
{
// code to create new file...omitted to conserve space
}
}
public class BlogDesigner:ControlDesigner
{
public override string GetDesignTimeHtml( )
{
return "<h1>Blog</h2><hr/><hr/>";
}
}
}
Adding Design-Time Support -Page 10
ASP.NET in a Nutshell
Adding Design-Time Support (Cont.) - Page 12
|