伸縮可能なパネルコントロール

jQueryのサーバーコントロール第一弾として伸縮可能なパネルコントロール「CollapsablePanel」を開発する。

画面イメージ


クラスコンポーネント仕様

Title
タイトル部分のテキスト
TitleForeColor
タイトル部分のテキスト色
TitleBackColor
タイトル部分の背景色
TitlePadding
タイトル部分の余白

実装

using System;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.WebControls;
using System.Text;
using System.Drawing;
using System.ComponentModel;
using System.Diagnostics;

namespace JQuery.Web.UI {
    public class CollapsablePanel : Panel {
        private string title = string.Empty;
        private Color titleBackColor = Color.DarkBlue;
        private Color titleForeColor = Color.Gainsboro;
        private Unit titlePadding = new Unit("2px");

        [DefaultValue("")]
        [Category("表示"), Description("パネルのタイトルです。")]
        public string Title {
            get { return title; }
            set { title = value; }
        }
        [Themeable(true)]
        [DefaultValue(typeof(Color), "DarkBlue")]
        [Category("表示"), Description("タイトルの背景色です。")]
        public Color TitleBackColor {
            get { return titleBackColor; }
            set { titleBackColor = value; }
        }
        [Themeable(true)]
        [DefaultValue(typeof(Color), "Gainsboro")]
        [Category("表示"), Description("タイトルの前景色です。")]
        public Color TitleForeColor {
            get { return titleForeColor; }
            set { titleForeColor = value; }
        }
        [Themeable(true)]
        [DefaultValue(typeof(Unit), "2px")]
        [Category("表示"), Description("タイトルの余白です。")]
        public Unit TitlePadding {
            get { return titlePadding; }
            set { titlePadding = value; }
        }

        public CollapsablePanel() {
        }

        protected override void Render(HtmlTextWriter writer) {
            writer.AddStyleAttribute(HtmlTextWriterStyle.Width, Width.ToString());
            writer.AddStyleAttribute(HtmlTextWriterStyle.Padding, "0px");
            writer.RenderBeginTag(HtmlTextWriterTag.Div);

            writer.AddStyleAttribute(HtmlTextWriterStyle.Color, TitleForeColor.Name);
            writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, TitleBackColor.Name);
            writer.AddStyleAttribute(HtmlTextWriterStyle.Margin, "0px");
            writer.AddStyleAttribute(HtmlTextWriterStyle.Padding, TitlePadding.ToString());
            writer.AddStyleAttribute(HtmlTextWriterStyle.TextAlign, "center");
            writer.AddAttribute(HtmlTextWriterAttribute.Id, this.UniqueID + "-title");
            writer.RenderBeginTag(HtmlTextWriterTag.P);
            writer.Write(Title);
            writer.RenderEndTag();

            writer.RenderBeginTag(HtmlTextWriterTag.Script);
            StringBuilder script = new StringBuilder();
            script.Append("$('#" + this.UniqueID + "-title').click(function() {");
            script.Append(" $('#" + this.UniqueID + "').slideToggle(); ");
            script.Append("});");
            writer.Write(script.ToString());
            writer.RenderEndTag();

            base.Render(writer);
        }

        protected override void OnLoad(EventArgs e) {
            base.OnLoad(e);

            ClientScriptManager csMgr = this.Page.ClientScript;
            csMgr.RegisterClientScriptResource(this.GetType(), "JQuery.script.jquery-1.2.1.js");
        }
    }
}

  1. Panelクラスから派生する。
  2. OnLoadメソッドをオーバーライドし、ClientScriptManagerクラスを使ってページにjQueryスクリプトを読み込む。
  3. Renderメソッドをオーバーライドし、Panelにタイトル部分をつけるHTMLを生成する。

Panelクラスは「div」要素を生成するだけなので、それを囲む「div」要素とタイトル文字列を表示する「p」要素を生成する。
簡単に説明するとこんな感じ↓

<div>
    <p>タイトル</p>
    <script type="text/javascript">
    </script>
    <div>
    </div>
</div>

あとデザイン時の見た目を制御するためのデザイナクラスを作成する。

internal class CollapsablePanelDesigner : ContainerControlDesigner {
    public override string FrameCaption {
        get {
            string title = ((CollapsablePanel)this.Component).Title;

            return title.Length != 0 ? title : base.FrameCaption;
        }
    }
    public override Style FrameStyle {
        get {
            Style style = new Style();
            style.CopyFrom(base.FrameStyle);
            style.BackColor = ((CollapsablePanel)this.Component).TitleBackColor;
            style.ForeColor = ((CollapsablePanel)this.Component).TitleForeColor;

            return style;
        }
    }
}

これをカスタム属性を使って、CollapsablePanelのデザイナクラスとして関連付ける。

[Designer(typeof(CollapsablePanel.CollapsablePanelDesigner))]
public class CollapsablePanel : Panel {

これでデザイン時にも実行時とほぼ同じ表示を得ることができる。
(より詳細な表示を得たい場合はGetDesignTimeHtmlをオーバーライドする必要がある)

これで完成。
ビルドしてからASPXページのデザイナを開けば、ツールボックスに「CollapsablePanel」が追加されているので、
それをASPXページにドラッグ&ドロップすれば使用できる。