C# Programming

ControlASP.NET 2.0 のコントロール

Button, LinkedButton, ImageButton, HyperLink

開発環境: Visual Studio 2005 

1.目次

1.目次
2.目的
3.参考書
4.ASP.NET 2.0 のコントロール
 4.1 ASP.NET 2.0 のコントロール
 4.2 OnClientClick
 4.3 Attributes の使用方法
 4.4 HyperLink コントロール
 4.5 ボタンコントロール
 4.6 リンクボタンコントロール
 4.7 ASP.NETを使う上での注意
 4.8 JavaScriptを書く場合の注意

2.目的

ちょっとしたページをASP.NETで作ろうと思ったところ、思いっきりはまりました。忘れないようにメモっておきます。

3.参考書

  1. MSDN: [HOWTO] ASP.NET で Visual Basic .NET を使用してクライアント側のイベントとサーバー側コントロールを関連付ける方法
  2. MSDN: WebControl.Attributes プロパティ
  3. MSDN: ボタンが押されたときに確認ダイアログを表示する方法

4.ASP.NET 2.0 のコントロール

ASP.NETを触っていて、コントロールからどのようなHTMLが生成されるのかを理解していないと、まともに組めないということがわかりました。そこで、ASP.NET WebコントロールがどのようなHTMLを生成するのか調べてみました。

4.1 ASP.NET 2.0 のコントロール

ボタンとリンクのコントロールの特徴をまとめると、次のようになります。表を見ていると、あれっ?と思いませんか?画像が表示でき、リンクに飛ぶことができ、Click, Commandイベントハンドラがあるコントロールがないんですよね。

これは、HyperLinkが生成するコードは <a id="HyperLink1" href="hhttp://....">HyperLink</a></div>というHTMLタグが生成され、ブラウザ側(クライアント側)でhrefへ飛ぶ処理が行われます。このため、リンクをクリックされたということをサーバ側(ASP.NET)側では感知できないためです。

カテゴリ タグ 説明 Click,
Command
OnClientClick NavigateURL
ボタン Button 普通のボタン ×
LinkButton スタイルがリンクになっているだけのボタン ×
ImageButton 画像を表示できるだけのボタン ×
リンク HyperLink 画像も表示できるリンク × ×

一方、ASP.NET 2.0から OnClientClickがサポートされており、これにより画像をクリックすることにより新しいウィンドウを開き、なおかつClickイベントハンドラの処理を行うということができるようになります。それについては、次のセクションで説明します。

4.2 OnClientClick

Button, LinkButton, ImageButtonなどでは、OnClientClickにより、クライアント側の処理を実行することができるようになっています。この機能により、MSDN: ボタンが押されたときに確認ダイアログを表示するということができるようになります。

また、次のように画像をクリックすると新しいページを開くと同時に、サーバ側でイベント処理をすることができるようになります。

画像をクリックすると新しいページを開くと同時に、サーバ側でイベント処理をする
< 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>
</head>
<body link="#000ce0">
    <form id="form1" runat="server">
        <asp:ImageButton ID="ImageButton1" runat="server" 
            ImageUrl="http://uchukamen.com/Images/UkamenLogo.gif"
            OnClick="ImageButton1_Click" 
            OnClientClick='alert("新しいウィンドウで開きます。");window.open("http://uchukamen.com");' />
    </form>
</body>
</html>

 

OnClientClickの注意

いろいろ試してみましたが、alert(), confirm(), window.open()は動くのですが、location.Replace()やプロパティの設定(location.url='abc')は動作しません。だいたいにおいて、MSDNやヘルプでOnClientClickの説明が不十分なのと、例が記載されいないので、どのように記述すればよいのか、あるいは何ができて何ができないのか不明です。一応、MS-USにフィードバックしておきました。

4.3 Attributes の使用方法

WebControl.Attributes プロパティは、名前と値のペアを持つコレクションで、Web サーバー コントロールに関連付けられている属性をプログラムで制御することができます。

次の例では、Button1コントロールのアトリビュートのOnClickとstyleにそれぞれスクリプトを追加します。通常は、Page_Loadイベントハンドラでアトリビュートの変更を行います。

Attributes の例
    protected void Page_Load(object sender, EventArgs e)
    {
        Button1.Attributes["OnClick"] = "alert('Attributes のテスト')";
        Button1.Attributes["style"] = "BACKGROUND-COLOR: #ccffff;";
    }
これにより次のように、生成されるHTMLのButton1に属性が追加されます。
<input type="submit" name="Button1" value="Button" 
   onclick="javascript: alert('Attributes のテスト');" 
   id="Button1" style="BACKGROUND-COLOR: #ccffff;" />

これにより、OnClientClickと同じようなことができます。

4.4 HyperLink コントロール

まずは、簡単なHyperLinkコントロールについてです。HperLinkコントロールを貼り付けた場合のHTMLは、次のようになります。

Image

 

生成された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>
</head>
<body>
    <form id="form1" runat="server">
        <asp:HyperLink ID="HyperLink1" runat="server" 
           NavigateUrl="http://uchukamen.com">HyperLink</asp:HyperLink>
    </form>
</body>
</html>

これからわかるように、<form> </form>タグの中にasp:HyperLinkコントロールが生成されています。

では、これを実行して表示されたWeb画面のソースコードを見てみます。

生成されたHTML
<!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><title>
	無題のページ
</title></head>
<body link="#000ce0">
    <form name="form1" method="post" action="Default.aspx" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" 
  value="/wEPDwUJNTkwNjIyODQxZGTwNE1rOPy7Ik+b7eJA2q6kN3obQg==" />
</div>
        <a id="HyperLink1" href="http://uchukamen.com">HyperLink</a>
    </form>
</body>
</html>

ここで、リンク本体は、<a id="HyperLink1" href="http://uchukamen.com">HyperLink</a>という形で生成されています 。input

4.5 ボタンコントロール

次は、ボタンコントロールです。

Image

 

生成された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>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Button ID="Button1" runat="server"
          OnClick="Button1_Click" Text="Button" /></div>
    </form>
</body>
</html>

ここで、ボタンを押したときにサーバ側に送信するために<form> </form>タグの中にasp:Button がformタグの中に生成されています。ボタンを押したときの動作は、Button1_Clickというイベントハンドラが...aspx.csに生成されていています。

では、これを実行して表示されたWeb画面のソースコードを見てみます。

生成されたHTML
<!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><title>
	無題のページ
</title></head>
<body>
    <form name="form1" method="post" action="Default.aspx" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE"
value="/wEPDwUKMTQ2OTkzNDMyMWRkaLkWe3SSdAOUq+q38g0m0EsouIQ=" />
</div>

    <div>
        <input type="submit" name="Button1" 
             value="Button" id="Button1" /></div>
        // ここがボタン本体
    
<div>

	<input type="hidden" name="__EVENTVALIDATION"
         id="__EVENTVALIDATION" 
             value="/wEWAgK6xOWfDgKM54rGBpDqUfyvW1XLChZibPehMyUfGlKm" />
</div></form>
</body>
</html>

ここで、ボタン本体は、<input type="submit" name="Button1" value="Button" id="Button1" />という形で生成されていますが、OnClickが消えています。
その代わり、<input type="hidden" ...> タグが2つ追加されており、__VIEWSTATEと__EVENTVALIDATIONというものが追加されています。

VIEWSTATEは、クライアント側の状態を記憶するためのものです。たとえば VIEWSTATEが無いと、クライアント側でチェックボタンにチェックしたとしても、ページをリフレッシュして、サーバからHTMLをリロードすると、チェックが消えてしまいます。このため、ASP.NETでは、チェックされていることなどのクライアント状態をVIEWSTATEとして、サーバに送信します。サーバでは、このことを記憶しておき、次にクライアントからHTMLの要求があったときに、VIEWSTATEにその情報を載せて、返信します。

さて、話を戻して、OnClick="Button1_Click"はどこに行ったのでしょうか。生成されたHTMLから、intutタグを削除して確かめて見ます。__VIEWSTATEのinputタグを削除し、ブラウザで表示してみると正常に動作します。一方、__EVENTVALIDATIONのinputタグを削除し、ブラウザで表示してみると次のようなエラーが表示されます。

「アプリケーションでサーバー エラーが発生しました。
--------------------------------------------------------------------------------

無効なポストバックまたはコールバック引数です。イベントの検証は、構成の <pages enableEventValidation="true"/>、またはページの <%@ Page EnableEventValidation="true" %> を使用して有効にされます。セキュリティの目的により、この機能は、イベントをポストバックまたはコールバックする引数が、それらを最初に表示したサーバー コントロールから発行されていることを確認します。データが有効であり、予期されている場合、検証のためのポストバックまたはコールバック データを登録するために ClientScriptManager.RegisterForEventValidation メソッドを使用してください。
説明: 現在の Web 要求を実行中に、ハンドルされていない例外が発生しました。エラーに関する詳細および例外の発生場所については、スタック トレースを参照してください。

例外の詳細: System.ArgumentException: 無効なポストバックまたはコールバック引数です。イベントの検証は、構成の <pages enableEventValidation="true"/>、またはページの <%@ Page EnableEventValidation="true" %> を使用して有効にされます。セキュリティの目的により、この機能は、イベントをポストバックまたはコールバックする引数が、それらを最初に表示したサーバー コントロールから発行されていることを確認します。データが有効であり、予期されている場合、検証のためのポストバックまたはコールバック データを登録するために ClientScriptManager.RegisterForEventValidation メソッドを使用してください。・・・」

このことから、__EVENTVALIDATIONは、ボタンコントロールからサーバに送信されるデータの受け渡しとそのデータの検証を行っており、セキュリティ対策も講じられていると考えられます。

4.6 リンクボタンコントロール

次は、リンクボタンコントロールです。ここでは確認のために OnClickイベントとOnClientClickプロパティをセットしてあります。

Image

 

生成された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>
</head>
<body link="#000ce0">
    <form id="form1" runat="server">
        <asp:LinkButton ID="LinkButton1" runat="server" 
             OnClick="LinkButton1_Click" 
             OnClientClick='alert("OnClientClick")'> 
                 LinkButton</asp:LinkButton>
    </form>
</body>
</html>

これからわかるように、サーバ側へボタンが押されたことを送信するために、<form> </form>タグの中にasp:LinkButtonが生成されています。サーバ側のイベントハンドラは、OnClick="LinkButton1_Click"、クライアント側の処理はOnClientClick='alert("OnClientClick")'というパラメータで渡されています。

では、これを実行して表示されたWeb画面のソースコードを見てみます。

生成されたHTML
<!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><title>
	無題のページ
</title></head>
<body link="#000ce0">
    <form name="form1" method="post" action="Default.aspx" id="form1">
<div>
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" 
    value="/wEPDwULLTE4NDIzMDg2NDRkZP3kLJ7ET0ucGldWzRUtevIJ+CLA" />
</div>

<script type="text/javascript">
<!--
var theForm = document.forms['form1'];
if (!theForm) {
    theForm = document.form1;
}
function __doPostBack(eventTarget, eventArgument) {
    if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
        theForm.__EVENTTARGET.value = eventTarget;
        theForm.__EVENTARGUMENT.value = eventArgument;
        theForm.submit();
    }
}
// -->
</script>

        <a onclick="alert("OnClientClick");" id="LinkButton1" 
            href="javascript:__doPostBack('LinkButton1','')">LinkButton</a>

<div>
	<input type="hidden" name="__EVENTVALIDATION" 
         id="__EVENTVALIDATION" 
            value="/wEWAgLtoIDrCQLM9PumD/e3BqmWpc26PZ0JE6IONC3r4bJ0" />
</div></form>
</body>
</html>

ボタンコントロールのときは、input type="submit"でしたが、今度は<a onclick="alert("OnClientClick");"でクライアント側の処理を行い、href="javascript: 関数()"という形でリンクを押したタイミングで関数をコールするという動作のHTMLが生成されています。このjavascript: 関数()をもう少し詳しく見ていくと、__doPostBackという javascriptの関数が上で定義されており、ここへボタンコントロールのインスタンス名が渡され、__doPostBack関数の中でsubmit()が呼び出され、サーバ側に情報が送信されるようになっています。

 

4.7 ASP.NETを使う上での注意

以上のように、コントロールの種類によって、生成されるASPX、最終的なHTML、処理の方法が異なってきます。ASP.NETでは、あたかもコントロールを貼り付けると簡単にWeb画面ができてしまうと思われるかもしれませんが、基本的には最終的にブラウザが理解できるHTMLやjavascriptの形に変換しているということを理解しておきましょう。逆に言えば、HTMLやjavascriptがもともと持つ制限事項は、ASP.NETだからといって対応できるとは限らないということです。

また、ASP.NETのコントロールだけでは対応できない場合でも、HTML, javascriptとの組み合わせで、対応できる可能性もあるということです。特に、ASP.NETコントロール以上のことをしようと思った場合には、HTML, javascriptの知識が必要になります。

4.8 JavaScriptを書く場合の注意

JavaScriptを手で書く場合、次のように<!-- と-->を追加します。これは JavaScriptを理解しないブラウザで表示した場合に、コードが丸見えになってしまうのを避けるためです。

JavaScriptを書く場合の注意
<!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>
   <title>
	無題のページ
   </title>
</head>

<body>

<script type="text/javascript">
<!--
  function abc()
  {
    ...
  }
// -->
</script>

</body>
</html>