2009年5月23日土曜日

asp.netでモーダルウィンドウ



お仕事で、モーダルダイアログを表示する箇所があったので、その開発メモ。


1.ポップアップブロック対応

ieでは、以下のような処理を行うと、「ポップアップはブロックされました。このポップアップまたは追加オプションを表示するにはここをクリックしてください」という表示がされてしまう。

webページのボタン押下

サーバのポストバック処理

サーバのボタンイベント処理

PCへjavascript起動を含めたページ返信

javascriptのwindow.openやshowModalDialogの実行

これは、ユーザ操作ではなく、サーバからページが送られた直後にウィンドウを新たに起こそうとしているため発生するので、ユーザ操作によるウィンドウオープンにすれば回避できそう。


具体的には、以下のようなaタグを作って表示しておくか、

<a href="javascript:window.showModalDialog('ポップアップウィンドウ?次画面への受け渡し用クエリストリング')">ウインドウオープン</a>


ボタンを配置し、Page_Loadで、ボタンのonClickイベントにdialogを仕込み、
protected void Page_Load(object sender, EventArgs e)
{
Button.Attributes["onClick"] = "javascript:window.showModalDialog('ポップアップウィンドウ?次画面への受け渡し用クエリストリング');return false;";
}
これらを押すことにより『ユーザの操作により』ウィンドウを開くようにすればよさそう。
だけど、上のようにすると作りが複雑になること、リンクやボタン押下時に自画面でのポストバック処理やイベント処理が動かないという制限がある。


今回この制限が回避不可能な見込みのためポップアップブロック回避は見送りになりそう。





2.モーダルダイアログを経由する画面遷移
今回、以下の4つのページを使っていろいろ実験をしてみる。(すべてのページにボタンが1つづつある)
FirstPage.aspx:起動時のページ1つボタンが置かれており、ボタン処理は以下の通り。
protected void Button1_Click(object sender, EventArgs e)
{
Page.ClientScript.RegisterClientScriptBlock(GetType(), "CreateModalDialog",
"<script language='javascript'>window.onload=function(){window.showModalDialog('SecondPage.aspx');}"
+ "</script>");
}


SecondPage.aspx :FirstPage.aspxから呼ばれるページ、ボタン処理は以下の通り。
protected void Button1_Click(object sender, EventArgs e)
{
Response.Redirect("ThirdPage.aspx");
}

ThirdPage.aspx:SecondPage.aspxから呼ばれるページ。ボタン処理は以下の通り。
protected void Button1_Click(object sender, EventArgs e)
{
Page.ClientScript.RegisterClientScriptBlock(GetType(), "CreateModalDialog",
"<script language='javascript'>window.onload=function(){window.showModalDialog('ForthPage.aspx');}"
+ "</script>");
}

ForthPage.aspx:ThirdPage.aspxから呼ばれるページ。ボタン処理は以下の通り。
protected void Button1_Click(object sender, EventArgs e)
{

}

これで、画面遷移をしてみると、「ポップアップブロック」以外に以下の問題が発生した。
・FirstPage.aspx→SecondPage.aspx→SecondPage.aspxを×で閉じる→FirstPage.aspx→SecondPage.aspxでSecondPage.aspxのPage_Load()が呼ばれないでSecondPage.aspxが表示される。(キャッシュの影響か?)
・ThirdPage.aspxが(画面遷移ではなく)新ウィンドウで表示される。

上の2点の対応で、SecondPage.aspxのヘッダタグに以下の記述を追加。
<meta http-equiv="pragma" content="no-cache" />
<base target="_self" />
一応こうすることで、SecondPage.aspxの2回目の呼び出しもPage_Load()が動いてくれたし、ThirdPage.aspxも自ウィンドウで表示された。

ただ、ThirdPage.aspxからForthPage.aspxに遷移するとき、ThirdPage.aspxが別のウィンドウで開いてしまう。
このため、ThirdPage.aspxにも、<base target="_self" />をつけてみたところ、今度は、ForthPage.aspxが開く前に、「オブジェクトでサポートされていないプロパティまたはメソッドです」のメッセージが。。。
showModalDialog()中に、「ポップアップブロック」が走るとエラーとなるみたい。
ThirdPage.aspxで、ボタンの2個目を追加して、aspx.csに以下の通りにすると、エラーなく、showDialogが2重で意図通りの動きになった。
protected void Page_Load(object sender, EventArgs e)
{
Button2.Attributes["onClick"] = "javascript:window.showModalDialog('ForthPage.aspx');return false;";
}


というわけで、showModalDialogのまとめ。

・showModalDialogで表示する画面とModalDialogウィンドウで遷移する画面すべてのヘッダタグ内に、<base target="_self" />を入れる必要がある。
・showModalDialogで表示する画面は、キャッシュされないように、ヘッダタグ内に、<meta http-equiv="pragma" content="no-cache" />を入れる必要がある。
・window.openと同様に、ユーザ操作なしにウィンドウを開く場合は「ポップアップブロック」が動く。
・showModalDialogの処理から「ポップアップブロック」が動くと、javascriptがエラーとなってしまう。

なので、今回、2重のshowModalDialog()を利用できるかは微妙になっちゃいました。

0 件のコメント: