none
Ajax DropDownListへフォーカスを移した場合にフォーカスが消える問題について RRS feed

  • 質問

  • Ajax DropDownListへフォーカスを移した場合にフォーカスが消える問題について

    下記のアプリケーションを作成して実行するとフォーカスが消えてしまいます。
    コントロールDropDownListをTextBoxにするとフォーカスは消えません。

    これは、コントロールDropDownListのバグなのでしょうか?
    それともInternet Explorer8のバグ?

    できれば回避方法があると助かります。
    大変困っており、だれか回避策をお持ちのかた、アドバイスをお願いいたします。


    下記の両環境で発生
     1..NET Framework3.5
     2..NET Framework2.0+Microsoft Ajax Toolkit

    ブラウザ
     1.Internet Explorer6/7      問題なし
     2.Internet Explorer8        現象が発生!!

    以下ソースです。

    ---Default.aspx
    
    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._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>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>    
        	<asp:ScriptManager ID="ScriptManager1" runat="server">
    		</asp:ScriptManager>
    		<br />
    		<asp:UpdatePanel ID="UpdatePanel1" runat="server">
    			<ContentTemplate>
    				<asp:TextBox ID="TextBox1" runat="server" AutoPostBack="True" 
    					ontextchanged="TextBox1_TextChanged"></asp:TextBox>
    				<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
    			</ContentTemplate>
    		</asp:UpdatePanel>
    		<br />
    		<asp:DropDownList ID="DropDownList1" runat="server">
    			<asp:ListItem>aaaaaa</asp:ListItem>
    			<asp:ListItem>bbbbbb</asp:ListItem>
    		</asp:DropDownList>
    		<br />
    		<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>    
        </div>
        </form>
    </body>
    </html>
    
    ---Default.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    
    namespace WebApplication1
    {
    	public partial class _Default : System.Web.UI.Page
    	{
    		protected void Page_Load(object sender, EventArgs e)
    		{
    
    		}
    
    		protected void TextBox1_TextChanged(object sender, EventArgs e)
    		{
    			Label1.Text += "!";
    		}
    	}
    }
    

     

    2009年9月2日 2:33

すべての返信

  • 補足ですが、
      1.Ajaxを使わない(UpdatePanelを外す)場合は、問題なく動きます。
         しかし、他がAjaxで動かしており、この部分だけが画面がカチカチ点滅するのは思わしくない。

      2.問題の出る操作方法ですが、
         テキストボックスの内容を変えて、Tabでフォーカスを抜けると非同期のAjax処理によりフォーカスが消えてしまいます。
        
         対処方法は、DropDownListボックスをTextBoxに変えるとフォーカスは消えません。
         しかし、当方の作成アプリはDropDownListボックスを使用しているのでTextBoxに変えることは出来ずに困っています。

         また、IE8だけ発生するというのもの悩みの種です。(互換表示だと大丈夫)

         対象ブラウザは、IE6/7/8なので、それ以外のfirefox、opera、safariなどは動かなくても問題ありません。

    以上
    2009年9月2日 2:44
  • Vista SP2 のローカル IIS7 モードで IE8 を使って試してみました。一部異なる点がありました
    が(後述)、フォーカスが消えるという問題は再現できました。

    DropDownList(HTML タグでは select)のイベントの発生を調べてみたところ、TextBox に入
    力して Tab キーでフォーカスが移って onfocus イベントが発生するものの、何故かすぐに
    onblur イベントが発生します。

    対症療法にしかならない(にもならない?)かもしれませんが、JavaScript で、以下のようなイ
    ベントハンドラを作って対処するというのはいかがでしょう?

    (1) onfocus イベントが発生したら、ごく短い時間フラグを立てる。

    (2) onblur イベントが発生したらフラグをチェックし、フラグが立っていたら focus() する。

    一応コードを書いて試してみましたが、ちらつきはなく(見えないだけでしょうが)、見かけは自然に
    フォーカスが移ってそのままとどまるようなります。

    ただ、「ごく短い時間」というのをどのくらいに設定するかが問題ですが。また、詳細には検証して
    ないので、もしバグがあったらすみません。

    なお、「一部異なる点」というのは以下の通りです。

    > 1.Ajaxを使わない(UpdatePanelを外す)場合は、問題なく動きます。

    UpdatePanel を削除するとポストバックがかかってフォーカスは消えます。(それが普通だと思い
    ますが)

    > (互換表示だと大丈夫)

    互換表示でも同じでした。

    2009年9月5日 6:40
  • SurferOnWww さん
    回答有難うございます。

    少しこちらで出ている現象と動きが異なるようですね。
    もし、違いがあるとすれば、なるほど、こちらは、XP SP3のIE8です。
    そのためかはわかりませんが、事象を参考させて頂きます。

    回答の
    JavaScriptのonfocusイベントとonblurイベントを使えば
    回避できそうです。しかし、Ajaxが非同期のイベントであり、且つ、それが
    回線帯域によってラグの時間差が異なるのでこの対応は難しいと考えております。

    できれば回線環境やサーバ側の処理のラグに影響されないかたちでの
    対応を求めます。

    引き続き調べていきます。
    2009年9月12日 3:21
  • > しかし、Ajaxが非同期のイベントであり、且つ、それが
    > 回線帯域によってラグの時間差が異なるのでこの対応は難しいと考えております。

    そうですね。フォーカスが消えるのは UpdatePanel 内が更新された時のようですので、それに時間が
    かかるようですと、先のメッセージに書いた「ごく短い時間」が、短くならなくなってしまいますから。

    > できれば回線環境やサーバ側の処理のラグに影響されないかたちでの
    > 対応を求めます。

    ScriptManager が取得するスクリプト (MicrosoftAjax.js) を書き換えるという手段もあるかもしれま
    せんが、自分には手が出せません。

    残る手段は、自力で帯域外呼び出しを実行するコードを実装するぐらいでしょうか。以下のような感じ
    です(コードの大部分は、マイクロソフト公式解説書「ASP.NET AJAX 入門」からのパクリです)。

    <%@ 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)
        {
            if (IsOutOfBand())
            {
                return;
            }
        }

        private bool IsOutOfBand()
        {
            bool isCallBack = false;
            string outofband = Request.QueryString["outofband"];
            isCallBack = String.Equals(outofband, "true", StringComparison.OrdinalIgnoreCase);

            if (isCallBack)
            {
                string param = Request.QueryString["param"];
                Response.Write(ExecutePageMethod(param));
                Response.End();
                return true;
            }
            return false;
        }

        string ExecutePageMethod(string eventArgument)
        {
            //System.Threading.Thread.Sleep(1000);
            return "You entered: " + eventArgument;
        }

    </script>

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head id="Head1" runat="server">
        <title></title>
        <script type="text/javascript">
        <!--
            function SendRequest(url, params) {
                var pageUrl = url + "?outofband=true&param=" + params;           
                var xmlRequest, e;

                try {
                    xmlRequest = new XMLHttpRequest();
                }
                catch (e) {
                    try {
                        xmlRequest = new ActiveXObject("Microsoft.XMLHTTP");
                    }
                    catch (e) {
                    }
                }

                xmlRequest.open("POST", pageUrl, false);
                xmlRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
                xmlRequest.send(null);           
                return xmlRequest;
            }

            function Info() {
                var text = document.getElementById("TextBox1").value;
                var xml = SendRequest("05_DropDownListFocus(2).aspx", text); // ファイル名は適宜変更して下さい
                var label = document.getElementById("Label1");
                label.innerHTML = xml.responseText;
            }
        //-->
        </script>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
      <input id="TextBox1" type="text" onchange="javascript:Info()" />   
      <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
      <br />
      <asp:DropDownList ID="DropDownList1" runat="server">
       <asp:ListItem>aaaaaa</asp:ListItem>
       <asp:ListItem>bbbbbb</asp:ListItem>
      </asp:DropDownList>
        </div>
        </form>
    </body>
    </html>

    • 回答の候補に設定 istb16 2009年10月2日 7:43
    2009年9月12日 6:02
  • SurferOnWww ユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダル さん、たびたびの回答をありがとうございます。

    頂いたコードで思い通りの動作をさせる事が出来ました!!

    頂いた回避策は、本当時に自前でAjaxを実装しており、UpdatePanelを使っていないのですね。
    当方はこれを最終手段の回避策として参考にさせて頂き、もう少し根本的な原因を調べていきます。

    なので、何か分かれば連絡をさせていただます。
    ありがとうございました。
    2009年9月15日 5:30