画像、html ファイル、スクリプトファイル、css ファイルなどのリソースをアセンブリに埋め込んで使用する、カスタムコントロールのサンプルです。
参考にしたのは、Microsoft サポートの Working with Web Resources in ASP.NET 2.0 です。サンプルコードほとんどそのままですが、CSS を参照する部分ほかを若干変更し、自分なりに注釈を加えてみました。
カスタムコントロールの本体は、table 要素の中に画像とアンカータグを配置したものです。mouseover、mouseout イベントで、コントロールの画像とラベルの色を変化させています。クリックすると、ヘルプページ Help.htm に遷移するようになっています。
必要な画像、html ファイル、スクリプトファイル、css ファイルなどのリソースは、すべてカスタムコントロールのアセンブリに埋め込んであります。
それらの内容は、以下の画像の通りです。MsButton.cs がカスタムコントロール本体、その他が埋め込んだりソースです。
ソースファイルの内容は以下の通りです。ソースを Visual Studio のプロジェクトに追加したら、上の画像のように、各リソースのプロパティのビルドアクションを「埋め込まれたりソース」に設定するのを忘れないようにしてください。その他、個別の注意点は下記の説明を参照してください。
実際に動かして試せるよう 実験室 にこのカスタムコントロールを使ったページをアップしましたので、興味のある方は試してみてください。
MsButton.cs
カスタムコントロールの本体です。基本は、table 要素の中に画像とアンカータグを配置したものです。
アセンブリに埋め込んだリソースは、GetWebResourceUrl メソッド によって URL 参照を取得して使用します。
2013/7/6 追記:this.GetType() ⇒ typeof(MsButton) に変更。詳細は リソース埋込カスタムコントロールの継承 を参照してください。
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.HtmlControls;
namespace SimpleControl
{
[ToolboxData(
"<{0}:MSButton runat='server' Text='Problems?'><{0}:MSButton>")]
public class MsButton : WebControl
{
[Category("Appearance")]
[DefaultValue("Problems?")]
[Description("Text for Label")]
[Localizable(true)]
[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public string Text
{
get
{
String s = (String)ViewState["Text"];
return ((s == null) ? String.Empty : s);
}
set
{
ViewState["Text"] = value;
}
}
protected override void CreateChildControls()
{
ClientScriptManager cs = Page.ClientScript;
// 2013/7/6 修正
// このコントロールを継承する場合 this.GetType() ではダメ
// this は継承先になり、結果、リソースが見つからない。
//Type rsType = this.GetType();
Type rsType = typeof(MsButton);
// css への参照を <head></head> に配置
HtmlLink css = new HtmlLink();
css.Href =
cs.GetWebResourceUrl(rsType,
"SimpleControl.MyStylesheet.css");
css.Attributes["rel"] = "stylesheet";
css.Attributes["type"] = "text/css";
Page.Header.Controls.Add(css);
Literal tableStart = new Literal();
tableStart.Text =
"<table cellspacing='0' cellpadding='0'>" +
"<tr><td valign='middle'>";
this.Controls.Add(tableStart);
HyperLink linkImage = new HyperLink();
linkImage.NavigateUrl =
cs.GetWebResourceUrl(rsType, "SimpleControl.Help.htm");
linkImage.Attributes.Add(
"onmouseover", "ChangeImage('image1','Green')");
linkImage.Attributes.Add(
"onmouseout", "RollbackImage('image1','Red')");
this.Controls.Add(linkImage);
Image img = new Image();
img.ImageUrl =
cs.GetWebResourceUrl(rsType,
"SimpleControl.smallFail.gif");
img.ID = "image1";
// ASP.NET 4 からは自動的に border-width を 0 に設定
// しなくなった
img.Style["border-width"] = "0";
linkImage.Controls.Add(img);
Literal ltTableColumn = new Literal();
ltTableColumn.Text = "</td><td valign='middle'>";
this.Controls.Add(ltTableColumn);
HyperLink linkText = new HyperLink();
linkText.NavigateUrl =
cs.GetWebResourceUrl(rsType, "SimpleControl.Help.htm");
linkText.Attributes.Add(
"onmouseover", "ChangeImage('image1','Green')");
linkText.Attributes.Add(
"onmouseout", "RollbackImage('image1','Red')");
this.Controls.Add(linkText);
Label lbl = new Label();
lbl.ID = "Label1";
lbl.Text = this.Text;
lbl.Font.Name = "Verdana";
lbl.Font.Bold = true;
lbl.Font.Size = FontUnit.Medium;
lbl.ForeColor = System.Drawing.Color.Red;
linkText.Controls.Add(lbl);
Literal tableEnd = new Literal();
tableEnd.Text = "</td></tr></table>";
this.Controls.Add(tableEnd);
// MyScript.js ファイルを参照するスクリプト
// ブロックを追加。
cs.RegisterClientScriptInclude(
"MyScript",
cs.GetWebResourceUrl(rsType,
"SimpleControl.MyScript.js"));
base.CreateChildControls();
}
}
}
MyScript.js
このクライアントスクリプトは、mouseover、mouseout イベントで、コントロールの画像とラベルの色を変化させるためのものです。
img 要素の src 属性に、アセンブリ内のリソース smallFail.gif と smallSuccess.gif を参照する URL を動的に取得して設定している点に注意してください。
そのためには、スクリプトの中で、<%= WebResource("アセンブリ内のパス") %> のように記述します。それによって、<%= ~ %> ブロックの中身は実行時に動的に解析され、出力時には、
WebResource.axd?d=p_b6vJYrM2mWH00RZ2d...faEA2&t=634730293148422703
といったURLが埋め込まれます。その場合、後述しますが、WebResource 属性を定義する際、PerformSubstitution プロパティを true にしておく必要がありますので注意してください。
なお、ここでは簡略化のため Labal1 というサーバー側の ID を直接使っていますが、クライアント側の id は異なる場合がありますので(例:マスターページを使う場合など)、実際の応用には注意してください。
function ChangeImage(imgControl, varcolor) {
document.getElementById(imgControl).src =
'<%=WebResource("SimpleControl.smallSuccess.gif")%>';
document.getElementById('Label1').style.color = varcolor;
}
function RollbackImage(imgControl, varcolor) {
document.getElementById(imgControl).src =
'<%=WebResource("SimpleControl.smallFail.gif")%>';
document.getElementById('Label1').style.color = varcolor;
}
MyStylesheet.css
スタイルを何も指定しないと、ハイパーリンクの文字列には、mouseover でアンダーラインが入ります。この CSS が有効なのでアンダーラインは入りません。
a {
text-decoration:none;
}
Help.htm
リソースに埋め込んだヘルプページです。コントロールをクリックすると、このページに遷移します。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>ヘルプのページ</title>
</head>
<body>
<h1>Help Page</h1>
<p>これはヘルプページです。</p>
</body>
</html>
AssemblyInfo.cs
アセンブリ内の指定された埋め込みリソースを Web リソースとして使用できるようにするため、WebResource 属性 を使用してメタデータ属性を定義します。
AssemblyInfo.cs ファイルは Visual Studio が自動生成しますので、その中に、以下のコードのように WebResource 属性の定義を追加します。(WebResourceAttribute クラス の説明のサンプルコードのように、クラスファイルに追加することもできます)
この中で、MyScript.js は、アセンブリ内のリソース smallFail.gif と smallSuccess.gif を参照している点が他と異なります。そのため、PerformSubstitution プロパティ を true にしています。
リソースのファイル名や名前空間(この例では SimpleControl)を間違えると、当然動きませんが、エラーもでないので原因が分からず、ハマったりするかもしれませんので注意してください。
また、リソースファイルを、プロジェクト直下でなく、別にフォルダを作ってそこに入れたりすると、名前空間が変わってきますので注意してください。例えば、プロジェクト直下に Resources というフォルダを作って、そこにリソースファイルを入れると、名前空間は SimpleControl ではなく、SimpleControl.Resources になります。
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Web.UI;
[assembly: AssemblyTitle("SimpleControl")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SimpleControl")]
[assembly: AssemblyCopyright("Copyright(c) 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 埋め込んだリソースが参照されるよう WebResource 属性を追
// 加。 これら以外は Visual Studio が自動生成したコード。
[assembly: WebResource("SimpleControl.Help.htm",
"text/html")]
[assembly: WebResource("SimpleControl.MyStylesheet.css",
"text/css")]
[assembly: WebResource("SimpleControl.smallFail.gif",
"image/gif")]
[assembly: WebResource("SimpleControl.smallSuccess.gif",
"image/gif")]
// MyScript.js は、アセンブリ内のリソース smallFail.gif
// と smallSuccess.gif を参照している。そのため、
// PerformSubstitution プロパティを true にしている。
[assembly: WebResource("SimpleControl.MyScript.js",
"text/javascript", PerformSubstitution = true)]
// WebResource 属性の追加はここまで。
[assembly: ComVisible(false)]
[assembly: Guid("3f6b9d6b-02db-48f8-acba-9cfe139a199a")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]