WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

リソース埋め込みカスタムコントロール

by WebSurfer 2012年5月19日 15:26

画像、html ファイル、スクリプトファイル、css ファイルなどのリソースをアセンブリに埋め込んで使用する、カスタムコントロールのサンプルです。

リソース埋め込みカスタムコントロール

参考にしたのは、Microsoft サポートの Working with Web Resources in ASP.NET 2.0 です。サンプルコードほとんどそのままですが、CSS を参照する部分ほかを若干変更し、自分なりに注釈を加えてみました。

カスタムコントロールの本体は、table 要素の中に画像とアンカータグを配置したものです。mouseover、mouseout イベントで、コントロールの画像とラベルの色を変化させています。クリックすると、ヘルプページ Help.htm に遷移するようになっています。

必要な画像、html ファイル、スクリプトファイル、css ファイルなどのリソースは、すべてカスタムコントロールのアセンブリに埋め込んであります。

それらの内容は、以下の画像の通りです。MsButton.cs がカスタムコントロール本体、その他が埋め込んだりソースです。

Visual Studio のソリューションエクスプローラーとプロパティウィンドウ

ソースファイルの内容は以下の通りです。ソースを 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")]

Tags:

Web Custom Control

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年3月  >>
252627282912
3456789
10111213141516
17181920212223
24252627282930
31123456

View posts in large calendar