none
EnterキーでDefaultButtonが動作した際、ValidationSummaryが表示されない RRS feed

  • 質問

  • <環境>
    Microsoft Visual Studio 2005
    Version 8.0.50727.762  (SP.050727-7600)
    Microsoft .NET Framework
    Version 2.0.50727 SP1


    ASP.NETで開発中、Subjectに挙げた現象に遭遇しました。



    Subjectが適切な要約になっている自信が無いので、順を追って書きます。


    まず、以下のようなPanelコントロール(+配下にButtonとTextBox)と、ValidationSumamryコントロールがあるASPXファイルがあります。

    <asp:Panel ID="Panel1" runat="server" DefaultButton="Button1">  
      <asp:TextBox id="TextBox1" runat="server" /> 
      <asp:RequiredFieldValidator ID="RequiredFieldValidator1"   
            runat="server" ErrorMessage="入力必須" ControlToValidate="TextBox1" Text="*" /> 
      <Button id="Button1" runat="server" Text="実行" /> 
    </asp:Panel> 
    <asp:ValidationSummary id="ValidationSummary1" runat="server" ShowMessageBox="True" ShowSummary="False" /> 


    期待する動作は、
    • TextBox1は入力必須で、未入力でButton1をクリックしてPostBackしようとすると、エラーメッセージを表示してPostBackを取りやめる
    • RequiredFieldValidator1に引っ掛かった場合、TextBox1の横に「*」を表示する。
    • TextBox1でEnterキーを押下した場合は、Button1をクリックしたのと同じ挙動とする。
    • 検証コントロールのエラーメッセージはValidationSummary にてalertで表示される。

    です。



    しかし、これを実行し、未入力状態のTextBox1にフォーカスがある状態でEnterキーを押下した場合の挙動が、期待するものと異なる部分が発生しました。


    <期待と一致する部分>

    • RequiredFieldValidatorにてPostBackがキャンセルさせる。
    • RequiredFieldValidatorのTextプロパティに設定された「*」が画面に表示される。


    <期待と異なる部分>

    • ShowMessageBoxをTrueにしているにも関わらず、ValidationSummaryによるalertが表示されない。



    なお、
     ・Button1を直接マウスでクリックした場合
     ・Button1にフォーカスがある状態でEnterキーを押下した場合
    は、期待通りにValidationSummaryが動作し、alertでメッセージが表示されます。

    また、
     ・ValidationSummaryのShowSummaryをTrueにした場合でも、サマリーは表示されない
    ことも確認しています(Buttonをクリックした場合はこちらも表示される)。




    今回は少し急いでいたため、RequiredFieldValidatorのEnableClientScriptをFalseにしてValidでなくてもPostBackさせ、サーバサイドにてIsValidをチェック、引っ掛かればクライアントに戻してalertを表示するような実装で対処しました。

    しかし、なんらか解決方法は無いものでしょうか?
    また、この現象、既知の現象としてKBなどでまとまっていたりしないでしょうか?
    http://forums.asp.net/t/1100563.aspx
    で同様の話題が出ていますが、このスレッド、及びここからリンクされているスレッドでも、上記の方法以上の対応方法は見当たらないように思いました。)




    以上、よろしくお願いいたします。


    きよくらならみ
    2009年2月25日 15:19

回答

  • VS2008だと、実行時のJavaScriptを含めてデバッグできるので、それでみてみたんですが、どうやらValidaterが関連づけられたテキストボックスの場合特殊な動きをしてるようです。
    常にテキストボックスへの入力(KeyPressかな?)が確認されており、keyCodeが13、つまりリターンキーの入力のときにいくつかのチェック処理がはしっています。
    この時点でエラーがあると、イベントのバブリングがとまるようで、デフォルトボタンのクリックというか、パネルのonkeypressイベントが発生していません。

    自動生成されるJavaScriptの動きをどうコントロールするか、という話になってくるので、対応はむずかしそうですね。
    あおい情報システム株式会社 小野修司(どっとねっとふぁん)
    • 回答としてマーク Kiyokura 2009年2月26日 5:00
    2009年2月26日 4:27

すべての返信

  • VS2008だと、実行時のJavaScriptを含めてデバッグできるので、それでみてみたんですが、どうやらValidaterが関連づけられたテキストボックスの場合特殊な動きをしてるようです。
    常にテキストボックスへの入力(KeyPressかな?)が確認されており、keyCodeが13、つまりリターンキーの入力のときにいくつかのチェック処理がはしっています。
    この時点でエラーがあると、イベントのバブリングがとまるようで、デフォルトボタンのクリックというか、パネルのonkeypressイベントが発生していません。

    自動生成されるJavaScriptの動きをどうコントロールするか、という話になってくるので、対応はむずかしそうですね。
    あおい情報システム株式会社 小野修司(どっとねっとふぁん)
    • 回答としてマーク Kiyokura 2009年2月26日 5:00
    2009年2月26日 4:27
  • >小野さん
    お世話になります。


    ああ、なるほど!
    DefaultButtonが云々ではなくて、そもそものValidatorの動きの話でしたか……。


    試しに元投稿のサンプルにValidationを行わないTextBoxを追加し、そこにフォーカスがある状態でEnterキーを押下してみると、その場合はValidationSummaryはちゃんと動作しますね。


    確かにこれをどうにかするのは、出来たとしてもHackの領域になってきそう(^^;に思います。
    #今回対応したようなサーバサイドでのチェックにするか、もしくは、そもそもの仕様を検討するにするべきなのかもしれませんね・・・…。



    検証していただき、ありがとうございましたm(__)m
    きよくらならみ
    2009年2月26日 5:01
  •  こんにちは!(^^)!ふ~です。

    CustomValidatorを使う手はどうでしょうか?
    これですと、クライアント側で検証が行えます。
    少し、改造すれば、使えそうな気もいたします。

    <ファイル名 Default.aspx >  
    <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %> 
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
     
    <html xmlns="http://www.w3.org/1999/xhtml">  
    <head runat="server">  
        <title>無題のページ</title> 
        <style type="text/css">  
            #Button1 {  
                width: 25px;  
            }  
        </style> 
    </head> 
     
    <script language="JavaScript">  
    <!--  
    var bButnF = false;  
    function Btn_ClientClick(){  
        //ボタン押下しました.  
        bButnF = true;  
    }  
     
    function cusTitle_Validate(sender, e){  
      if (e.Value.length != 0) {  
        e.IsValid = true;  
      }else{  
        e.IsValid = false;  
        if (bButnF == false )  
        {  
            // テキストボックスの場合  
            alert("-Custom Validator");        
        }  
        bButnF = false;  
      }  
    }  
    //--> 
    </script> 
     
    <body> 
        <form id="form1" runat="server">  
        <div> 
        <asp:Panel ID="Panel1" runat="server">  
        <asp:TextBox ID="TextBox1" runat="server" CausesValidation="True" /> 
        <asp:CustomValidator ID="CustomValidator1" runat="server" ControlToValidate="TextBox1" ErrorMessage="CustomValidator"   
     
    ClientValidationFunction="cusTitle_Validate" ValidateEmptyText="True" /> 
        <asp:Button id="Button1" runat="server" Text="実行" Width="65px" onclientclick="Btn_ClientClick()" />    
        </asp:Panel>    
        <asp:ValidationSummary id="ValidationSummary1" runat="server" ShowMessageBox="True" />    
        </div> 
        </form> 
    </body> 
    </html> 
     
    以上
    2009年2月26日 7:08
  • >!(^^)!ふ~ さん

    なるほど、既存のValidatorの動作によるところが原因ならCustomValidatorでどうにかしてしまえ、というのは、確かにアリかもしれませんね。


    今回、一度サーバにPostBackすることが仕様的に許容範囲でしたのでサーバサイドでやってしまいましたが(その方が実装的には楽だったため)、クライアントサイドで完結させる必要性が高い場合には選択肢の一つになりそうです。


    参考にさせて戴きます。
    ありがとうございました。
    きよくらならみ
    2009年2月26日 13:28
  •  

    !(^^)!ふ~さん>

    > CustomValidatorを使う手はどうでしょうか?

    それでも TextBox にフォーカスがあるときに Enter キーを押した場合、
    ValidationSummary は表示されないので、RequiredFieldValidator を使
    うのと同じになりませんか?

    2009年2月26日 14:10
  •  

    Kiyokura さん>

    期待する動作とは違うので、回答にはなっていないかもしれませんが・・・

    TextBox にフォーカスがあるとき Enter キーを押しても何も起こらないようにする
    というのはいかがですか?

    具体的には、Page_Load で

    TextBox1.Attributes.Add("onkeydown", "if (event.keyCode == 13) return false;");

    とするということですが。そうすれば検証はボタンクリックのときしか起こらなく
    なって、TextBox にフォーカスがあるとき Enter キーを押したときと動作が違う
    という問題は避けることができると思います。

    2009年2月26日 14:15
  • >SurferOnWwwさん

    見た目の挙動を一致させるなら、その対応も選択肢の一つかもしれませんね。

    実のところ、当初はまさにそのような実装で、Enterキーを読み捨てていたんですが、ユーザからの要望とその他処理要件を検討した結果、Enterキー押下でPostBackを発生させるのがベター、という結論に至ったため、DefaultButtonプロパティを使用するに至ったという経緯が今回はありまして(^^;

     

    昨晩も色々いじってみててた結果、元々のHogeValidatorの挙動と性質からすると、私の望むような挙動を簡単に実現するのは難しそうだなぁ、とは思います。

     

    あと、!(^^)!ふ~さんさんが提示してくださった例だと、TextBoxフォーカス時のEnterキー押下では自力でalertを表示するので、TextBoxが一つの時は私の望む動作に作りこめます。が、複数になってくると(まあ、ValidationSummaryの本来の使い方になりますか)、そのままだと二重実装気味になるので辛いかもですね。

    Javascriptから、『他のValidatorのIsValidも纏めてチェックし必要ならValidationSummaryの動作をキックする』とかが出来たりすると実現できそうなんですけど、単純な組み合わせではしんどそう……(--)

     

    現状だと、多分そこまでやるなら、要件的にPostBackが許されるならAjaxによる部分更新と組み合わせてサーバサイドでチェックして自分でSummaryを組み立ててやるほうが、実装工程も保守工程でも有利になっちゃいますね、きっと(^^;


    きよくらならみ
    2009年2月27日 0:50
  • おはようございます!(^^)!ふ~です。

    ValidationSummary は表示されないのでは!?、ValidationSummaryの動作をキックする!?

    そうですか、イマイチでした。再度、ValidationSummaryの表示も含める場合は、少々改造が必要です。

    <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %> 
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
     
    <html xmlns="http://www.w3.org/1999/xhtml">  
    <head runat="server">  
        <title>無題のページ</title> 
        <style type="text/css">  
            #Button1 {  
                width: 25px;  
            }  
        </style> 
    </head> 
     
    <script language="JavaScript">  
    <!--  
    var bButnF = false;  
    function Btn_ClientClick(){  
        //ボタン押下しました.  
        bButnF = true;  
    }  
     
    function cusTitle_Validate(sender, e){  
      if (e.Value.length != 0) {  
        e.IsValid = true;  
      }else{  
        e.IsValid = false;  
        if (bButnF == false )  
        {  
            Page_IsValid = false;  
            Page_Validators[0].isvalid = false;  
            ValidationSummaryOnSubmit(""); //パラメータはグループ名を渡す。  
        }  
        bButnF = false;  
      }  
    }  
    //--> 
    </script> 
     
    <body> 
        <form id="form1" runat="server">  
        <div> 
        <asp:Panel ID="Panel1" runat="server">  
        <asp:TextBox ID="TextBox1" runat="server" CausesValidation="True" /> 
        <asp:CustomValidator ID="CustomValidator1" runat="server" ControlToValidate="TextBox1" ErrorMessage="CustomValidator" ClientValidationFunction="cusTitle_Validate" ValidateEmptyText="True" /> 
        <asp:Button id="Button1" runat="server" Text="実行" Width="65px" onclientclick="Btn_ClientClick()" />    
        </asp:Panel>    
        <asp:ValidationSummary id="ValidationSummary1" runat="server" ShowMessageBox="True" />    
        </div> 
        </form> 
    </body> 
    </html> 
     

     <ポイント>
    Page_Validators[0].isvalid = false;  ここで、複数ある場合は[0]~[Max]で対応可能と思われます。

    以上

    2009年2月27日 1:13
  •  

    普通に RequiredFieldValidator を使って、以下のようにするのはいかがですか?
    スクリプトは以下のサイトからコピペして ValidationSummaryOnSubmit(); を追加
    しました。十分に検証していないので、バグがあったらすみません。あくまで参考
    程度ということで・・・

    検証コントロールのスクリプト ライブラリのサンプル
    http://msdn.microsoft.com/ja-jp/library/aa720565(VS.71).aspx

    <%@ Page Language="C#" %> 
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
     
    <script runat="server">  
     
        protected void Page_Load(object sender, EventArgs e)  
        {  
            TextBox1.Attributes.Add("onkeydown", "if (event.keyCode == 13) Page_ClientValidate();");  
        }  
    </script> 
     
    <html xmlns="http://www.w3.org/1999/xhtml">  
    <head runat="server">  
        <title></title>  
    </head> 
    <body> 
        <form id="form1" runat="server">  
        <div> 
            <asp:Panel ID="Panel1" runat="server" DefaultButton="Button1">     
                <asp:TextBox id="TextBox1" runat="server" />    
                <asp:RequiredFieldValidator ID="RequiredFieldValidator1"      
                    runat="server"   
                    ErrorMessage="入力必須"   
                    ControlToValidate="TextBox1"   
                    Text="*" />    
                <asp:Button id="Button1" runat="server" Text="実行" />    
            </asp:Panel>    
            <asp:ValidationSummary id="ValidationSummary1"   
                runat="server"   
                ShowMessageBox="True"   
                ShowSummary="False" /> 
        </div> 
        </form> 
    </body> 
    </html> 
    <script type="text/javascript">  
    <!--  
        function Page_ClientValidate() {  
            var i;  
            for (i = 0; i < Page_Validators.length; i++) {  
                ValidatorValidate(Page_Validators[i]);  
            }  
            ValidatorUpdateIsValid();  
            ValidationSummaryOnSubmit();    // 追加  
            Page_BlockSubmit = !Page_IsValid;  
            return Page_IsValid;  
        }  
    //--> 
    </script> 
    2009年2月27日 14:35
  •  

    自分でスクリプトを書かなくても、WebResource.axd?d=... の中に Page_ClientValidate(validationGroup)
    が定義されていて、それを呼べば同じような動作をするようです。

    要するに、先に自分がアップしたコードでスクリプトは不要で、単に Page_Load の中で、

    TextBox1.Attributes.Add("onkeydown", "if (event.keyCode == 13) Page_ClientValidate();");

    としてやれば同じ動作をしました。

    validationGroup を渡さない場合、IsValidationGroupMatch は true 返すので、正しく処置し
    てくれるようです。

    でも、標準では ValidationSummary が表示されないようになっているのには何か理由があって、
    無理(?)に上記のようなことをすると副作用(問題)が出るのかもしれませんね。

    2009年3月1日 4:03
  •  こんにちは!(^^)!ふ~です。

    こちらでも、Page_ClientValidate()だけで上手く動作しています。最近にない、お宝発見です。

    >TextBox1.Attributes.Add("onkeydown", "if (event.keyCode == 13) Page_ClientValidate();");

    MSDNのライブラリの中で、TextBox1.Attributes.Addに関して、下記ページに少し説明がございました。

    方法 : ASP.NET Web サーバー コントロールにクライアント スクリプト イベントを追加する
    http://msdn.microsoft.com/ja-jp/library/7ytf5t7k.aspx

    抜粋『ASP.NET コントロールにクライアント イベント ハンドラをプログラムによって追加するには
    ページの Init イベントまたは Load イベントで、Attributes コレクションのコントロールの Add メソッド
    を呼び出します。』

    ところが、デバッガー解析で見つけたのですが、クライアント側だけで同様な動作をするValidationSummaryOnSubmit()
    については、MSDNのライブラリで説明している箇所が見つかりません。ご使用している方も多いと思いますが情報が欲しいと
    ころです。
    2009年3月1日 8:32