Custom ASP.NET server control with embedded resources
Let’s take as an example a ColorPicker control that I recently made.
First, let’s create a New Project -> Web -> ASP.NET Server Control.
By default name of the project would be your default namespace. I called my project WebControls. I renamed ServerContol1.cs into ColorPicker.cs. I changed the default namespace to Karpach.WebControls, as well as
assembly name. Then I added to the project images, javascripts, and styles that I need for my color picker control.
Click on each file’s properties and change Build Action from Content to Embedded Resource.
Now lets modify AssemblyInfo.cs.
You need to register all your resources like this:
[assembly: System.Web.UI.WebResource("Karpach.WebControls.Images.SliderHandle.gif", "img/gif")]
[assembly: System.Web.UI.WebResource("Karpach.WebControls.Images.TabCenterActive.gif", "img/gif")]
[assembly: System.Web.UI.WebResource("Karpach.WebControls.Images.TabLeftActive.gif", "img/gif")]
[assembly: System.Web.UI.WebResource("Karpach.WebControls.Images.TabLeftInactive.gif", "img/gif")]
[assembly: System.Web.UI.WebResource("Karpach.WebControls.Images.TabRightActive.gif", "img/gif")]
[assembly: System.Web.UI.WebResource("Karpach.WebControls.Images.TabRightInactive.gif", "img/gif")]
[assembly: System.Web.UI.WebResource("Karpach.WebControls.Images.ColorPickerIcon.jpg", "img/jpeg")]
[assembly: System.Web.UI.WebResource("Karpach.WebControls.Styles.ColorPicker.css", "text/css")]
[assembly: System.Web.UI.WebResource("Karpach.WebControls.Javascript.ColorPicker.js", "text/js")]
As you notice System.Web.UI.WebResource first parameter has the following signature:
[Assembly Name].[Folder].[File Name] // this is very important, since it is not documented even in MSDN
Let’s move to ColorPicker.cs Modify ToolboxData to look like this:
[ToolboxData("<{0}:ColorPicker runat=server></{0}:ColorPicker>")]
Next, you probably want a custom icon in Visual Studio Toolbox.
After ToolboxData add the following line:
[System.Drawing.ToolboxBitmap(typeof(ColorPicker), "Images.color\_picker\_icon.jpg")]
Where the first parameter is a type of control and the second parameter icon file name used in AssemblyInfo.cs
Then you need to load stored resources from DLL. The best event for this is OnInit:
// Javascript
string colorFunctions = Page.ClientScript.GetWebResourceUrl(typeof(ColorPicker), "Karpach.WebControls.Javascript.ColorPicker.js");
Page.ClientScript.RegisterClientScriptInclude("ColorPicker.js", colorFunctions);
//Images
string script = string.Format(@"
var colorPicker = new ColorPicker();
colorPicker.FormWidgetAmountSliderHandleImage = '{0}';
colorPicker.TabRightActiveImage = '{1}';
colorPicker.TabRightInactiveImage = '{2}';
colorPicker.TabLeftActiveImage = '{3}';
colorPicker.TabLeftInactiveImage = '{4}';
", Page.ClientScript.GetWebResourceUrl(typeof(ColorPicker), "Karpach.WebControls.Images.SliderHandle.gif")
, Page.ClientScript.GetWebResourceUrl(typeof(ColorPicker), "Karpach.WebControls.Images.TabRightActive.gif")
, Page.ClientScript.GetWebResourceUrl(typeof(ColorPicker), "Karpach.WebControls.Images.TabRightInactive.gif")
, Page.ClientScript.GetWebResourceUrl(typeof(ColorPicker), "Karpach.WebControls.Images.TabLeftActive.gif")
, Page.ClientScript.GetWebResourceUrl(typeof(ColorPicker), "Karpach.WebControls.Images.TabLeftInactive.gif")
);
Page.ClientScript.RegisterStartupScript(Page.GetType(), "InitColorPicker", script, true);
// CSS
bool linkIncluded = false;
foreach (Control c in Page.Header.Controls)
{
if (c.ID == "ControlPickerStyle")
{
linkIncluded = true;
}
}
if (!linkIncluded)
{
HtmlGenericControl csslink = new HtmlGenericControl("link");
csslink.ID = "ColorPickerStyle";
csslink.Attributes.Add("href", Page.ClientScript.GetWebResourceUrl(typeof(ColorPicker), "Karpach.WebControls.Styles.ColorPicker.css"));
csslink.Attributes.Add("type", "text/css");
csslink.Attributes.Add("rel", "stylesheet");
Page.Header.Controls.Add(csslink);
}
Then used the RenderContents event to render the control HTML:
Table table = new Table();
table.Rows.Add(new TableRow());
table.Rows[0].Cells.Add(new TableCell());
table.Rows[0].Cells.Add(new TableCell());
HtmlInputText txt = new HtmlInputText();
txt.Attributes.CssStyle.Add(HtmlTextWriterStyle.Color, Color);
txt.Size = 15;
txt.Value = Color;
txt.MaxLength = 15;
txt.ID = ColorInputControlClientId;
txt.Name = ColorInputControlClientName;
table.Rows[0].Cells[0].Controls.Add(txt);
HtmlInputImage btn = new HtmlInputImage();
btn.Src = Page.ClientScript.GetWebResourceUrl(typeof(ColorPicker), "Karpach.WebControls.Images.ColorPickerIcon.jpg");
btn.Attributes.Add("onclick", string.Format("colorPicker.ShowColorPicker(this,document.getElementById('{0}'));return false;", ColorInputControlClientId));
table.Rows[0].Cells[1].Controls.Add(btn);
table.Rows[0].Cells[1].Attributes.CssStyle.Add(HtmlTextWriterStyle.Position, "relative");
table.RenderControl(output);
Now, final touch: minification of javascript and css.I used yahoo YUI compressor and Microsoft MSBuild. Here is final msbuild file:
<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildCommunityTasksPath>..\References</MSBuildCommunityTasksPath>
<ProjectName>WebControls</ProjectName>
</PropertyGroup>
<Target Name="Compress">
<Message Text="Create temp files …" />
<Copy SourceFiles=".$(ProjectName)\Javascript\ColorPicker.js" DestinationFiles=".$(ProjectName)\Javascript\ColorPicker.js.full"/>
<Copy SourceFiles=".$(ProjectName)\Styles\ColorPicker.css" DestinationFiles=".$(ProjectName)\Styles\ColorPicker.css.full"/>
<Exec Command="java -jar yuicompressor-2.4.2.jar –type js .$(ProjectName)\Javascript\ColorPicker.js.full >.$(ProjectName)\Javascript\ColorPicker.js"/>
<Exec Command="java -jar yuicompressor-2.4.2.jar –type css .$(ProjectName)\Styles\ColorPicker.css.full >.$(ProjectName)\Styles\ColorPicker.css"/>
</Target>
<Import Project=".\References\MSBuild.Community.Tasks.targets" />
<Target Name="Build" DependsOnTargets="Compress">
<Message Text="Building Project" />
<MSBuild Projects="./$(ProjectName)/$(ProjectName).sln" Properties="Configuration=Release;Platform=Any CPU" />
</Target>
</Project>
Now you even don’t need Visual Studio to compile DLL. All that you need is .NET 2.0 installed and then the following console script will do compilation:
%SystemRoot%\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe Build.proj /t:Build
Screenshot:
Thanks to the dhtmlgoodies.com for javascript source, see Color Picker