none
ポストバック要因がユーザーコントロール内のコントロールの場合、処理を行わないようにしたい RRS feed

  • 質問


  • ○環境等:ASP.NET 4.0、Windowsフォームアプリケーション

    ○ユーザーコントロール概要
    ・UpdatePanel(コントロール含む)、タイマーを配置しております。
    ・ユーザーコントロールは、主に現在時刻を1秒おきに表示更新するために使用しております。

    ○フォーム概要
    ・上記ユーザーコントロール、UpdatePanel(コントロール含む)、タイマーを配置しております。
    ・フォームでは1秒ごとにDBを参照し、DBの内容に応じて表示内容の更新を行っております。
    (フォームは複数あり、各フォームでユーザーコントロールを使用しています)


    ○現状の処理

    フォームのタイマーが指定時間経過するたびに
     フォームのPage_Load(ポストバック時の処理) → (※1)
     フォームのタイマーイベントハンドラ
    の処理が行われます。

    また、フォーム内にユーザーコントロールを配置しているため、
    ユーザーコントロールのタイマーが指定時間経過するたびに
     フォームのPage_Load(ポストバック時の処理) → (※1)
     ユーザーコントロールのPage_Load(ポストバック時の処理) → 
     ユーザーコントロールのタイマーイベントハンドラ
    の処理が行われます。


    ○質問
    フォーム/ユーザーコントロール どちらのタイマーが時間経過しても
    フォームのPage_Load(ポストバック時の処理)(※1)が行われるため、冗長と感じております。
    フォームのタイマーが時間経過したときのみ上記(※1)処理を行いたいと考えております。

    ・ユーザーコントロールのタイマーが時間経過したときに
     フォームのPage_Load(ポストバック時の処理)を行わないような方法は
     ありますでしょうか。

    フォームのPage_Loadでポストバックの発生要因となったコントロールのIDを取得し、
    そのIDがユーザーコントロールに配置されたタイマーであれば(※1)処理を
    飛ばすなどはできると思うのですがこのような方法が一般的な方法でしょうか。(※2)


    ソースコード(簡略化したもの)を添付します

    ------------------------------------------------------------------
    ソースコード(フォーム)

    ○WebForm8.aspx
        <form id="form1" runat="server">
            <asp:ScriptManager ID="ScriptManager1" runat="server">
            </asp:ScriptManager>

            <%--ユーザーコントロール--%>
            <uc1:UC1 ID="UC" runat="server" />

            <asp:Panel ID="Panel1" runat="server" Style="; top: 50px;">
                <asp:UpdatePanel ID="UpdatePanel1" runat="server">
                    <ContentTemplate>

                        <%--1秒ごとにフォーム内容の更新--%>
                        <asp:TextBox ID="TextBox1" runat="server" Width="250px"></asp:TextBox>

                    </ContentTemplate>
                    <Triggers>
                        <asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" />
                    </Triggers>
                </asp:UpdatePanel>
            </asp:Panel>

            <asp:Timer ID="Timer1" runat="server" Interval="1000" OnTick="Timer1_Tick">
            </asp:Timer>
        </form>


    ○WebForm8.aspx.cs

        public partial class WebForm8 : System.Web.UI.Page
        {
            static int postBackCount = 1;

            protected void Page_Load(object sender, EventArgs e)
            {
                if (!ScriptManager1.IsInAsyncPostBack && !IsPostBack)
                {
                    System.Diagnostics.Debug.WriteLine("   Page_Load PostBack でない");

                    // 略
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine("   Page_Load PostBack");

                    // PostBack時の処理(※1 略)

                    // ※2
                    // ここでポストバック要因がユーザーコントロールのタイマーならば
                    // 何も行わないようにするのが一般的な方法でしょうか?

                    postBackCount++;
                }
            }

            protected void Timer1_Tick(object sender, EventArgs e)
            {
                TextBox1.Text = string.Format("Form Timer {0} {1}回目", DateTime.Now.ToString("yyyy/MM/dd hh:mm:ss"), postBackCount);
            }
        }


    ------------------------------------------------------------------
    ソースコード(ユーザーコントロール)
    ○WebUserControl1.ascx

    <asp:Panel ID="Panel1" runat="server" BackColor="#CCFFFF" 
        style="; top:5px; left:5px; width: 188px; height:37px;">

        <asp:Timer ID="TimerUC" runat="server" Interval="1000" ontick="TimerUC_Tick">
        </asp:Timer>

        <asp:UpdatePanel ID="UpdatePanelUC" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="False">
            <ContentTemplate>

                <%--1秒ごとに現在時刻更新--%>
                <asp:TextBox ID="TextBoxUC" runat="server" 
                    style="; top:10px; left:10px; width: 150px;"></asp:TextBox>
            </ContentTemplate>

            <Triggers>
                <asp:AsyncPostBackTrigger ControlID="TimerUC" EventName="Tick" />
            </Triggers>
        </asp:UpdatePanel>
    </asp:Panel>

    ○WebUserControl1.ascx.cs

        public partial class WebUserControl1 : System.Web.UI.UserControl
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                if (!IsPostBack)
                {
                    System.Diagnostics.Debug.WriteLine("UC Page_Load PostBackでない");
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine("UC Page_Load PostBack");
                }
            }

            protected void TimerUC_Tick(object sender, EventArgs e)
            {
                System.Diagnostics.Debug.WriteLine("UC Timer1_Tick");
                this.TextBoxUC.Text = DateTime.Now.ToString("yyyy/MM/dd hh:mm:ss");
            }
        }

    2017年7月15日 6:43

回答

  • 回答ではなくて質問です。

    (1) 「環境等:ASP.NET 4.0、Windowsフォームアプリケーション」とありますが、Web Forms アプリケーションの間違いですね?

    (2) User Control はサーバー側の時刻を 1 秒毎に取得するためだけのものですか? そうだとすると、ひどく無駄なことをしていると思うのですが。クライアントスクリプトだけでポストバックせず PC の時刻を取得して表示するのではだめなんですか?

    時刻の取得・表示以外に、何かサーバー側でなければできない別のこともしているのではないかと想像しているのですが、であれば何をしているか書いてください。

    (3) 質問者さんのやりたいこと、

    > フォームのタイマーが時間経過したときのみ上記(※1)処理を行いたいと考えております。

    は、フォームのタイマー Tick イベントのハンドラで処置することでできないのですか?

    ScriptManager + UpdatePanel を使って非同期ポストバックをかけた場合、サーバー側では PreRender の前あたりまでは同期ポストバックと全く同じ動きになります。なので、Load イベントは必ず発生し、そこで処置を行っているとすると、何ともならないと思うのですが。


    • 編集済み SurferOnWww 2017年7月15日 8:21 タイポ訂正
    • 回答としてマーク cow bell 2017年7月16日 8:28
    2017年7月15日 8:20

すべての返信

  • 回答ではなくて質問です。

    (1) 「環境等:ASP.NET 4.0、Windowsフォームアプリケーション」とありますが、Web Forms アプリケーションの間違いですね?

    (2) User Control はサーバー側の時刻を 1 秒毎に取得するためだけのものですか? そうだとすると、ひどく無駄なことをしていると思うのですが。クライアントスクリプトだけでポストバックせず PC の時刻を取得して表示するのではだめなんですか?

    時刻の取得・表示以外に、何かサーバー側でなければできない別のこともしているのではないかと想像しているのですが、であれば何をしているか書いてください。

    (3) 質問者さんのやりたいこと、

    > フォームのタイマーが時間経過したときのみ上記(※1)処理を行いたいと考えております。

    は、フォームのタイマー Tick イベントのハンドラで処置することでできないのですか?

    ScriptManager + UpdatePanel を使って非同期ポストバックをかけた場合、サーバー側では PreRender の前あたりまでは同期ポストバックと全く同じ動きになります。なので、Load イベントは必ず発生し、そこで処置を行っているとすると、何ともならないと思うのですが。


    • 編集済み SurferOnWww 2017年7月15日 8:21 タイポ訂正
    • 回答としてマーク cow bell 2017年7月16日 8:28
    2017年7月15日 8:20
  • SurferOnWww様

    ご回答いただきありがとうございます。
    質問時の説明不足等が多く申し訳ありません。

    > (1) Web Forms アプリケーションの間違いですね?

    はい、そうです。失礼いたしました。



    > (2) クライアントスクリプトだけでポストバックせず PC の時刻を取得して表示するのではだめなんですか?

    こちらも説明不足でした。
    User Control はでサーバー側の時刻を表示しています。
    あとは、複数のフォームで共通表示する画像やテキスト(タイトル画像や○○システムといった文言など)を配置しています。




    > (3) 質問者さんのやりたいこと、
    > > フォームのタイマーが時間経過したときのみ上記(※1)処理を行いたいと考えております。
    > は、フォームのタイマー Tick イベントのハンドラで処置することでできないのですか?

    こちらについては、確認します。
    従来の処理をできるだけ変えないように と思っていたので
    処理が重複しているかもしれませんし、まとめられると思います。


    > ScriptManager + UpdatePanel を使って非同期ポストバックをかけた場合、サーバー側では PreRender の前あたりまでは同期ポストバックと全く同じ動きになります。
    > なので、Load イベントは必ず発生し、そこで処置を行っているとすると、何ともならないと思うのですが。

    はい。やはり、行いたいようなことを行うとすると、
    if文等でポストバック要因ごとに分岐ということになりますでしょうか。


    • 回答としてマーク cow bell 2017年7月16日 6:41
    • 回答としてマークされていない cow bell 2017年7月16日 8:27
    2017年7月16日 6:38
  • 自分のレスに「回答としてマーク」を付けてますが、自分で回答して解決したのですかね?

    どう見てもそうは思えませんが、もし解決したというならどのように解決したのか書いてください。


    2017年7月16日 7:46
  • SurferOnWww様

    ご連絡いただきありがとうございます。
    たびたび失礼いたしました。

    SurferOnWww様にご回答いただきました
    > Load イベントは必ず発生し、そこで処置を行っているとすると、何ともならないと思うのですが。

    にチェックを付けたつもりでしたが、操作を間違ってしまいました。

    分岐が必要であれば、if文等でポストバック要因ごとに分岐ということになるのだろうと判断いたしました。
    経験が浅いため、今後もお世話になることがあるかと思いますが、
    その際はまたご指導よろしくお願いいたします。



    2017年7月16日 8:34
  • > 分岐が必要であれば、if文等でポストバック要因ごとに分岐ということになるのだろうと判断いたしました。

    Page_Load ハンドラで処置することにこだわっておられるようですが、そうしなければならない理由があるのですか?

    先のレスでも書きましたが、フォームのタイマー Tick イベントのハンドラでも処置することができるのであれば、その方が簡単ですよね。if 文で分岐とか考えなくて済みますから。

    質問者さんのやっていることがよくわからないので可能かどうかわかりませんが、以下のような順序で解決策を考えるのが普通だと思うのですが。

    (1) User Control での時刻の取得はクライアント側だけで行う。

    (2) それがダメでどうしてもサーバーの時刻を取得する必要があるなら、Load イベントが発生してしまう ScriptManager + UpdatePanel による非同期ポストバックを使うのではなく、Web サービス + jQuery ajax を使って時刻の取得のみを行う。

    (3) それもダメなら、Load イベントハンドラで処置を行うのではなく、フォームのタイマー Tick イベントのハンドラで処置を行うようにする。

    if 文で分岐とか考えるのは (1) ~ (3) 全てダメな場合だと思います。

    と言って、どういう条件で判断するかは難しいところだと思いますが。



    2017年7月16日 10:18