none
Webコントロールライブラリのプロパティについて RRS feed

  • 質問

  • 現在VS.2005にて、Webカスタムコントロールを作成しております。

    プロパティとして、ボタンコントロールそのものを公開しようとしております。
    そのプロパティを介して、ボタンのTextプロパティなどは設定できるのですが、
    Clickイベントの設定がうまく反映されず困っております。
    ソースコードは以下の通りです。

    ---------------------------------------------------------------------------------
    Webカスタムコントロール側(WebCustomControl1.dll)
    ---------------------------------------------------------------------------------
    namespace WebControlLibrary1
    {
        [ToolboxData("<{0}:WebCustomControl1 runat=server></{0}:WebCustomControl1>")]
        public class WebCustomControl1 : WebControl
        {
            private Button btn;

            public Button Btn
            {
                get { return btn; }
            }

            public WebCustomControl1()
            {
                btn = new Button();
            }

            protected override void RenderContents(HtmlTextWriter output)
            {
                btn.RenderControl(output);
            }
        }
    }

    ---------------------------------------------------------------------------------
    Webページ側(Default.aspx.cs)
    ---------------------------------------------------------------------------------
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Init(object sender, EventArgs e)
        {
         // IDを"wcc"とする
            Button btn = this.wcc.Btn;
           
            // Textプロパティは正常に表示される
            btn.Text = "ボタン";
           
            // ClickイベントとしてWCC_Clickを実行したい
            // (実際は実行されない)
            btn.Click += new EventHandler(WCC_Click);
        }

        protected void WCC_Click(object sender, EventArgs e)
        {
            this.Label1.Text = "テストです";
        }
    }

    実際にWebカスタムコントロールに配置するボタンは複数あり、
    それに対応するすべてのイベントを作成するのは困難です。

    そのため、ボタンそのものを公開したいと考えております。

    上記のようにボタンそのものをプロパティとして、
    イベントを実行する方法をご存知の方、お教え下さいますでしょうか?
    以上、宜しくお願い致します。

    2006年3月21日 8:13

回答

  • う~ん、例えば以下のような感じでしょうか? ざくっと作ったので、もっと工夫の必要があるのではないかと思います。
     




     namespace WebControlLibrary1
    {
        [ToolboxData("<{0}:WebCustomControl1 runat=server></{0}:WebCustomControl1>")]
        public class WebCustomControl1 : WebControl, IPostBackEventHandler
        {
            public delegate void ClickBtnEventHandler(object sender, ClickBtnEventArgs e);
            public event ClickBtnEventHandler ClickBtn;
     
             public class ClickBtnEventArgs : EventArgs
            {
                string _ButtonName;
     
                 public string ButtonName
                {
                    get { return _ButtonName; }
                }
     
                 public ClickBtnEventArgs(string buttonName)
                {
                    _ButtonName = buttonName;
                }
            }
     
             private Button _Btn1;
            private Button _Btn2;
            private Button _Btn3;
     
             public Button Btn1
            {
                get { return _Btn1; }
            }
     
             public Button Btn2
            {
                get { return _Btn2; }
            }
     
             public Button Btn3
            {
                get { return _Btn3; }
            }
     
             public WebCustomControl1()
            {
                _Btn1 = new Button();
                _Btn2 = new Button();
                _Btn3 = new Button();
            }
     
             public void RaisePostBackEvent(String eventArgument)
            {
                switch (eventArgument)
                {
                    case "btn001":
                        ClickBtn(_Btn1, new ClickBtnEventArgs("btn001"));
                        break;
                    case "btn002":
                        ClickBtn(_Btn2, new ClickBtnEventArgs("btn002"));
                        break;
                    case "btn003":
                        ClickBtn(_Btn3, new ClickBtnEventArgs("btn003"));
                        break;
                }
            }
     
             protected override void RenderContents(HtmlTextWriter output)
            {
                output.WriteBeginTag("input");
                output.WriteAttribute("type", "submit");
                output.WriteAttribute("name", "btn001");
                output.WriteAttribute("value", _Btn1.Text);
                output.WriteAttribute("OnClick", Page.ClientScript.GetPostBackEventReference(this, "btn001"));
                output.WriteEndTag("input");
     
                 output.WriteBeginTag("input");
                output.WriteAttribute("type", "submit");
                output.WriteAttribute("name", "btn002");
                output.WriteAttribute("value", _Btn2.Text);
                output.WriteAttribute("OnClick", Page.ClientScript.GetPostBackEventReference(this, "btn002"));
                output.WriteEndTag("input");
     
                 output.WriteBeginTag("input");
                output.WriteAttribute("type", "submit");
                output.WriteAttribute("name", "btn003");
                output.WriteAttribute("value", _Btn3.Text);
                output.WriteAttribute("OnClick", Page.ClientScript.GetPostBackEventReference(this, "btn003"));
                output.WriteEndTag("input");
            }
        }
    }
     
     
    public partial class custumControl : System.Web.UI.Page
    {
        protected void Page_Init(object sender, EventArgs e)
        {
            Button btn1 = this.WebCustomControl1_1.Btn1;
            Button btn2 = this.WebCustomControl1_1.Btn2;
            Button btn3 = this.WebCustomControl1_1.Btn3;
     
             btn1.Text = "ボタン1";
            btn2.Text = "ボタン2";
            btn3.Text = "ボタン3";
     
             WebCustomControl1_1.ClickBtn += new WebCustomControl1.ClickBtnEventHandler(WCC_Click);
        }
     
         protected void WCC_Click(object sender, WebCustomControl1.ClickBtnEventArgs e)
        {
            switch (e.ButtonName)
            {
                case "btn001":
                    this.Label1.Text = "ボタン1クリック!";
                    break;
                case "btn002":
                    this.Label1.Text = "ボタン2クリック!";
                    break;
                case "btn003":
                    this.Label1.Text = "ボタン3クリック!";
                    break;
            }
        }
     
     }

     

    2006年3月23日 5:18
    モデレータ

すべての返信

  • カスタムコントロールのイベントは、その中でのみ発生し、そのコンテナ(親)では捕まえることができません。
    また、今回のButtonコントロールであるbtnは、WebCustomControl1の内部に持っているクラスであるため、ポストバックの処理に関しても自前で記述する必要があります。以下を参考にすれば、実現できるでしょう。

    件名:[ASP.NET] 独自のWebコントロールにOnClickイベントの追加
    http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=28488&forum=7&2

     

    2006年3月22日 9:00
    モデレータ
  • ご返信ありがとうございます。

    今回は複数ボタンを配置する予定ですので、お教え頂いた方法ですと、

    以下のどちらかの方法を採用することになると考えます。

    パターン1.事前にボタンの数だけイベントを追加&公開しておく

    パターン2.DataGridのItemCommandに相当するようなイベントを公開しておき、
          EventArgs等で、どのボタンがクリックされたかコントロールの
          利用者から判断できるようにしておく。
          ※イベントの処理の振り分けは、利用者任せとなる。

    ボタンコントロールに対して、直接イベントハンドラを追加できるようにしておいた方が、
    利用者にとっては分かりやすいと考えていたのですが・・。
    擬似的 or 無理やりでも構いませんので、何とか方法はありませんでしょうか?

    2006年3月22日 12:02
  • >今回は複数ボタンを配置する予定ですので

    Webページにおいて、Webカスタムコントロールであるボタンをいくつも配置するように思ったのですが、違いますでしょうか?
    これであれば、必要なだけツールボックスよりボタンをドラッグ&ドロップしてきて、それらのボタンにイベントハンドラを付けていくだけです。

    2006年3月23日 1:31
    モデレータ
  • 言葉足らずで申し訳ありません。

    具体的な仕様用途をお伝えしますと、
    一般的な業務アプリケーションにおける、システムメニュー画面を想定しております。
    システムメニューとしまして、以下のコントロールの配置を考えています。

     ・ボタン × N:(各業務画面に遷移させる)
     ・テキストボックス:(ボタンコントロールに採番された番号を入力することにより、
                ボタン押下のイベントを実行)

    上記ボタンコントロールの「N」はプロパティにて公開し、
    自由にボタンの数を増減できることを想定しております。

    そして各ボタンは、規定の「各業務画面に遷移させる」という動作の他に、
    自由にイベントの追加を行えるようにしたいと考えております。

    以上の機能を持った、
    言うなれば「システムメニュー・コントロール」の作成を行いたいのです。

    マスタページやテンプレート機能を使えば、
    ある程度ならカスタムコントロールの作成と同様の効果を得られるかも知れませんが、
    今回はカスタムコントロールの作成を行おうと考えています。

    今のところは先に記述しました、
    パターン2のItemCommandに相当するイベントの追加で対処したいと考えております。
    データグリッドなどと同様のインターフェースの方がコントロールの利用者としては
    分かりやすいかもしれません。

    ただ、やはり技術的に気になりますので、
    何らかの方法で実装可能なのか知りたいところです。

    2006年3月23日 3:10
  • う~ん、例えば以下のような感じでしょうか? ざくっと作ったので、もっと工夫の必要があるのではないかと思います。
     




     namespace WebControlLibrary1
    {
        [ToolboxData("<{0}:WebCustomControl1 runat=server></{0}:WebCustomControl1>")]
        public class WebCustomControl1 : WebControl, IPostBackEventHandler
        {
            public delegate void ClickBtnEventHandler(object sender, ClickBtnEventArgs e);
            public event ClickBtnEventHandler ClickBtn;
     
             public class ClickBtnEventArgs : EventArgs
            {
                string _ButtonName;
     
                 public string ButtonName
                {
                    get { return _ButtonName; }
                }
     
                 public ClickBtnEventArgs(string buttonName)
                {
                    _ButtonName = buttonName;
                }
            }
     
             private Button _Btn1;
            private Button _Btn2;
            private Button _Btn3;
     
             public Button Btn1
            {
                get { return _Btn1; }
            }
     
             public Button Btn2
            {
                get { return _Btn2; }
            }
     
             public Button Btn3
            {
                get { return _Btn3; }
            }
     
             public WebCustomControl1()
            {
                _Btn1 = new Button();
                _Btn2 = new Button();
                _Btn3 = new Button();
            }
     
             public void RaisePostBackEvent(String eventArgument)
            {
                switch (eventArgument)
                {
                    case "btn001":
                        ClickBtn(_Btn1, new ClickBtnEventArgs("btn001"));
                        break;
                    case "btn002":
                        ClickBtn(_Btn2, new ClickBtnEventArgs("btn002"));
                        break;
                    case "btn003":
                        ClickBtn(_Btn3, new ClickBtnEventArgs("btn003"));
                        break;
                }
            }
     
             protected override void RenderContents(HtmlTextWriter output)
            {
                output.WriteBeginTag("input");
                output.WriteAttribute("type", "submit");
                output.WriteAttribute("name", "btn001");
                output.WriteAttribute("value", _Btn1.Text);
                output.WriteAttribute("OnClick", Page.ClientScript.GetPostBackEventReference(this, "btn001"));
                output.WriteEndTag("input");
     
                 output.WriteBeginTag("input");
                output.WriteAttribute("type", "submit");
                output.WriteAttribute("name", "btn002");
                output.WriteAttribute("value", _Btn2.Text);
                output.WriteAttribute("OnClick", Page.ClientScript.GetPostBackEventReference(this, "btn002"));
                output.WriteEndTag("input");
     
                 output.WriteBeginTag("input");
                output.WriteAttribute("type", "submit");
                output.WriteAttribute("name", "btn003");
                output.WriteAttribute("value", _Btn3.Text);
                output.WriteAttribute("OnClick", Page.ClientScript.GetPostBackEventReference(this, "btn003"));
                output.WriteEndTag("input");
            }
        }
    }
     
     
    public partial class custumControl : System.Web.UI.Page
    {
        protected void Page_Init(object sender, EventArgs e)
        {
            Button btn1 = this.WebCustomControl1_1.Btn1;
            Button btn2 = this.WebCustomControl1_1.Btn2;
            Button btn3 = this.WebCustomControl1_1.Btn3;
     
             btn1.Text = "ボタン1";
            btn2.Text = "ボタン2";
            btn3.Text = "ボタン3";
     
             WebCustomControl1_1.ClickBtn += new WebCustomControl1.ClickBtnEventHandler(WCC_Click);
        }
     
         protected void WCC_Click(object sender, WebCustomControl1.ClickBtnEventArgs e)
        {
            switch (e.ButtonName)
            {
                case "btn001":
                    this.Label1.Text = "ボタン1クリック!";
                    break;
                case "btn002":
                    this.Label1.Text = "ボタン2クリック!";
                    break;
                case "btn003":
                    this.Label1.Text = "ボタン3クリック!";
                    break;
            }
        }
     
     }

     

    2006年3月23日 5:18
    モデレータ
  • サンプルのご提示、誠にありがとうございます。

    ご提示頂いた内容ですと、先述したパターン2となります。
    やはりそのやり方が一番スマートなのですね。

    ボタン毎にイベントを追加させる方法は見送り、
    今回はご提示頂いたサンプルを参考に、開発を進めようと考えます。

    貴重な時間を割いて頂き、重ねて御礼申し上げます。

    2006年3月23日 6:20
  • >やはりそのやり方が一番スマートなのですね。

    一番スマートかどうかはわかりません。(^^; れんぽんさんの要件に近いパターンで簡単にコーディングしただけです。れんぽんさんが示されたパターン1の方が良い場合もあるかもしれませんし、他にもっと良い方法があるかもしれません。
    上に上げたコードがベストだとは、とてもとても思っていません。添削入りそうですし。(^^;;
    でも、ポストバックを実装する方法と、子のイベントを親に伝える方法という基本的な事柄は、短いながら上のコードに織り込まれていますので、そこからいろいろと発展できると思います。

    2006年3月23日 9:59
    モデレータ