Implementing a ViewAsText property for a WebControl at design time
Sometimes all you want is a little change. Something simple like “View as Text” in design view.
There are starting to be a reasonable number of articles about Design-Time Support for Web Forms , there is Nikhil Kothari’s book, and Scott Mitchell has begun to write about them. When I started working on designers there were a lot fewer resources, but I learned some interesting stuff along the way.
This is my first blog about design time, and it is a simple article. I’m going to take two controls and give each of them a new property called ViewAsText.
I will use this property to decide if the control will display normaly or if it will display the html found in the html view.
The two controls are CustomLabel which inherits Label and CustomDropDownList which inherits DropDownList. Both controls have a view as text property, the label’s defaults to true, the dropdown's to false.
Each control has an associated designer. It is in the designers that we do something different, we override GetDesignTimeHtml so that we can return custom markup. The trick here is to get the html; I use the designer’s DesignTimeElement and cast it as an mshtml.IHTMLElement. From this element I get the innerHTML or outerHTML and procede to display it.
//The Controls
using System;
using System.Web.UI;
using
System.Web.UI.WebControls;
using
System.ComponentModel;
using
System.ComponentModel.Design;
using
AndrewSeven.Samples.Design;
[assembly:TagPrefix("AndrewSeven.Samples",
"AndrewSeven")]
namespace AndrewSeven.Samples
{
[Designer(typeof(CustomLabelDesigner),typeof(IDesigner))]
public
class CustomLabel : Label
{
private bool
viewAsText = true;
[DefaultValue(true)]
public
bool ViewAsText
{
get{return viewAsText;}
set{viewAsText
= value;}
}
}
[Designer(typeof(CustomDropDownListDesigner),typeof(IDesigner))]
public
class CustomDropDownList : DropDownList
{
private
bool viewAsText = false;
[DefaultValue(false)]
public
bool ViewAsText
{
get{return viewAsText;}
set{viewAsText
= value;}
}
}
}
//The designers
using System;
using System.IO;
using
System.Xml;
using System.Web.UI;
using System.Web.UI.WebControls;
using
System.Web.UI.Design;
using
System.Web.UI.Design.WebControls;
using
System.Web.UI.HtmlControls;
using System.Web.Caching;
using
System.ComponentModel;
using System.Globalization;
using
System.Configuration;
using
System.ComponentModel.Design;
using System.Collections;
using System.Reflection;
using System.Diagnostics;
using System.Threading;
using System.Text;
using
UITemplates;
using mshtml;
[assembly:TagPrefix("AndrewSeven.Samples", "UITemplates")]
//using System.Windows.Forms;
namespace
AndrewSeven.Samples.Design
{
public class
CustomLabelDesigner : LabelDesigner
{
DesignerVerb
viewAsTextVerb ;
DesignerVerb viewNormalVerb ;
CustomLabel
_targetControl;
public CustomLabelDesigner():base()
{
BuildVerbs();
}
private
void BuildVerbs()
{
viewAsTextVerb = new
DesignerVerb("View as Text" ,new
EventHandler(this.OnViewAsText));
viewNormalVerb =
new DesignerVerb("View Normal" ,new
EventHandler(this.OnViewNormal));
Verbs.Add(viewAsTextVerb);
Verbs.Add(viewNormalVerb);
}
private
CustomLabel TargetControl
{
get
{
if(_targetControl==null)
{
_targetControl
= this.Component as CustomLabel;
}
return
_targetControl;
}
}
private
void SetViewAsText(bool newValue)
{
if(TargetControl.ViewAsText!=newValue)
{
TargetControl.ViewAsText=newValue;
this.RaiseComponentChanged(null,"","");
}
viewAsTextVerb.Enabled
= !newValue;
viewNormalVerb.Enabled = newValue;
}
private
void OnViewAsText(object sender, EventArgs e)
{
SetViewAsText(true);
}
private
void OnViewNormal(object sender, EventArgs e)
{
SetViewAsText(false);
}
public override string GetDesignTimeHtml()
{
SetViewAsText(TargetControl.ViewAsText);
string
baseGetDesignTimeHtml = base.GetDesignTimeHtml();
if(
TargetControl.ViewAsText)
{
IHTMLElement copy =
((mshtml.IHTMLElement)this.DesignTimeElement);
string dtHTML =
(string)copy.outerHTML;
if(dtHTML
==null)
{
dtHTML = " ";
}
if(dtHTML.Length
> 0 && dtHTML.IndexOf("<") > -1)
{
dtHTML
= dtHTML.Replace("<","<");
}
return
"<table border=1
width='99%'><tr><td><pre>" +
dtHTML +"</pre></td></tr></table>";
}
else
{
return
baseGetDesignTimeHtml;
}
}
}
public class CustomDropDownListDesigner :
ListControlDesigner
{
DesignerVerb
viewAsTextVerb ;
DesignerVerb viewNormalVerb ;
CustomDropDownList
_targetControl;
public CustomDropDownListDesigner():base()
{
BuildVerbs(false);
}
private
void BuildVerbs(bool viewAsTextVisible)
{
viewAsTextVerb
= new DesignerVerb("View as Text" ,new
EventHandler(this.OnViewAsText));
viewNormalVerb =
new DesignerVerb("View Normal" ,new
EventHandler(this.OnViewNormal));
Verbs.Add(viewAsTextVerb);
Verbs.Add(viewNormalVerb);
}
private
CustomDropDownList TargetControl
{
get
{
if(_targetControl==null)
{
_targetControl
= this.Component as CustomDropDownList;
}
return
_targetControl;
}
}
private void
SetViewAsText(bool newValue)
{
if(TargetControl.ViewAsText!=newValue)
{
TargetControl.ViewAsText=newValue;
this.RaiseComponentChanged(null,"","");
}
viewAsTextVerb.Enabled
= !newValue;
viewNormalVerb.Enabled = newValue;
}
private
void OnViewAsText(object sender, EventArgs e)
{
SetViewAsText(true);
}
private
void OnViewNormal(object sender, EventArgs e)
{
SetViewAsText(false);
}
public override string GetDesignTimeHtml()
{
try
{
SetViewAsText(TargetControl.ViewAsText);
string baseGetDesignTimeHtml =
base.GetDesignTimeHtml();
//baseGetDesignTimeHtml
will have the rendered select tag with options...
if( TargetControl.ViewAsText)
{
IHTMLElement copy =
((mshtml.IHTMLElement)this.DesignTimeElement);
string dtHTML =
(string)copy.innerHTML;
if(dtHTML
==null)
{
dtHTML = " ";
}
if(dtHTML.Length
> 0 && dtHTML.IndexOf("<") > -1)
{
dtHTML
= dtHTML.Replace("<","<");
}
return
"<table border=1
width='99%'><tr><td><pre>" +
dtHTML +"</pre></td></tr></table>";
}
else
{
return
baseGetDesignTimeHtml;
}
}
catch
(Exception ex)
{
return ex.ToString();
}
}
}
}
And an aspx page from my sample
<%@ Register TagPrefix="AndrewSeven"
Namespace="AndrewSeven.Samples"
Assembly="TemplatedSampleSite" %>
<%@ Page
language="c#" Codebehind="DesignTimeHtmlView.aspx.cs"
AutoEventWireup="false"
Inherits="TemplatedSampleSite.examples.DesignTimeHtmlView"
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0
Transitional//EN" >
<HTML>
<HEAD>
<meta
content="Microsoft Visual Studio 7.0"
name="GENERATOR">
<meta content="C#"
name="CODE_LANGUAGE">
<meta
content="JavaScript" name="vs_defaultClientScript">
<meta
content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
</HEAD>
<body>
<form
id="DesignTimeHtmlView" method="post" runat="server">
<P>
<hr>
<AndrewSeven:CustomLabel
id="DesignViewHtmlControl1s" runat="server">
[HERE
]
<TITLE>Design Time Html Views</TITLE>
<META
content="MainTemplate.aspx" name="Template Source">
</AndrewSeven:CustomLabel>
<hr>
<AndrewSeven:CustomDropDownList
id="CustomDropDownList1" runat="server"
ViewAsText="True">
<asp:ListItem
Value="0000000000000">0000000000000</asp:ListItem>
<asp:ListItem
Value="111111111111">111111111111</asp:ListItem>
<asp:ListItem
Value="2222222222">2222222222</asp:ListItem>
</AndrewSeven:CustomDropDownList>
<hr>
<AndrewSeven:CustomLabel
id="Customlabel1" runat="server" Text='<%# "BoundValue"
%>' >
</AndrewSeven:CustomLabel>
<HR>
</form>
</body>
</HTML>