SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

japan.internet.com翻訳記事

クライアントサイドスクリプトを使ってGridView上のすべてのチェックボックスをオンにする方法

ヘッダー行で下位のチェックボックスすべてのオン/オフを管理する

  • X ポスト
  • このエントリーをはてなブックマークに追加

問題2

 ヘッダーのCheckBoxをオンにすると、グリッド上のすべてのチェックボックスがオンになるのですから、当初私は、ヘッダーのCheckBoxは一定のアクション(具体的に言うと、グリッド上のすべての下位チェックボックスをオンにするアクション)を単独で実行するユーザーインターフェイス項目であると考えていました。しかし実際には、ヘッダーのCheckBoxは、グリッド上のチェックボックスの状態を反映しているに過ぎません。つまり、ヘッダーのCheckBoxがオンになっていれば、グリッド上のすべての他のチェックボックスもオンになっていることを意味します。ヘッダーチェックボックスがオフになっていれば、グリッド上のチェックボックスの1個以上がオフになっています。

 このような事情を勘案すれば、グリッド上の他のチェックボックスがすべて手動でオンにされたときにヘッダーチェックボックスが自動的にオンになるような仕組みが必要なことは明らかです。またその反対に、その他のすべてのチェックボックスがオンにされた後でその1個が手動でオフにされた場合は、ヘッダーチェックボックスが自動的にオフになる必要もあります。この仕組みを実現するため、次のように修正することにしました。

  1. ChangeHeaderAsNeeded()というJavaScript関数を追加し、この関数の中で、グリッド上の他のCheckBoxがすべてオンの場合はヘッダーのCheckBoxをオンにし、オフのCheckBoxが1個でもある場合はヘッダーのCheckBoxをオフにする。
  2. 下位の各CheckBoxのクライアントサイドonclickイベントがChangeHeaderAsNeeded()関数を呼び出すように関連付ける。

 まずはChangeHeaderAsNeeded()関数を見ていきましょう。この関数では、CheckBoxIDs配列の最初の要素がヘッダーのCheckBoxのIDであり、それ以外の要素が下位CheckBoxのIDであることを前提としています。ループを使って下位CheckBoxを1つずつチェックして、オンかどうかを確認します。オンではないCheckBoxが1つでもあれば、ヘッダーのCheckBoxをオフにして関数を終了します。オフの下位CheckBoxが見つからないままループが終わった場合は、ヘッダーのCheckBoxをオンにします。

function ChangeHeaderAsNeeded()
{
    // Whenever a checkbox in the GridView is toggled, we need to
    // check the Header checkbox if ALL of the GridView checkboxes are
    // checked, and uncheck it otherwise
    if (CheckBoxIDs != null)
    {
        // check to see if all other checkboxes are checked
        for (var i = 1; i < CheckBoxIDs.length; i++)
        {
            var cb = document.getElementById(CheckBoxIDs[i]);
            if (!cb.checked)
            {
                // Whoops, there is an unchecked checkbox, make sure
                // that the header checkbox is unchecked
                ChangeCheckBoxState(CheckBoxIDs[0], false);
                return;
            }
        }

        // If we reach here, ALL GridView checkboxes are checked
        ChangeCheckBoxState(CheckBoxIDs[0], true);
    }
}

 次に、下位CheckBoxを設定して、クライアントサイドonclickイベントの発生時にChangeHeaderAsNeeded()関数が呼び出されるようにします。具体的には、以下のクライアントサイドコードをPage_Loadイベントハンドラ内のFor Eachループに追加します。

Protected Sub Page_Load(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles Me.Load
    ... Code omitted for brevity ...
    For Each gvr As GridViewRow In FileList.Rows
        'Get a programmatic reference to the CheckBox control
        Dim cb As CheckBox = _
            CType(gvr.FindControl("RowLevelCheckBox"), CheckBox)

        'If the checkbox is unchecked, ensure 
        'that the Header CheckBox is unchecked
        cb.Attributes("onclick") = "ChangeHeaderAsNeeded();"

        'Add the CheckBox's ID to the client-side CheckBoxIDs array
        ClientScript.RegisterArrayDeclaration( _
            "CheckBoxIDs", String.Concat("'", cb.ClientID, "'"))
    Next
End Sub

 これで終わりです。この変更により、すべてのチェックボックスを手動でオンにするとヘッダーのCheckBoxがオンになります。同様に、すべての下位チェックボックスがオンのときに1個のチェックボックスをオフにすると、ヘッダーのCheckBoxがオフになります。

ヘッダーのCheckBoxのIDが常に最初にあると前提しても安全か?

 ChangeHeaderAsNeeded()関数では、ヘッダーのCheckBoxのIDが常にCheckBoxIDs配列の最初のIDであることを前提としています。でも、この前提は常に正しいのでしょうか? コードでは、下位CheckBoxのIDを追加する前にヘッダーのCheckBoxのIDを追加するので、そう信じる根拠はあります。ヘッダーのCheckBoxのIDは、CheckBoxIDs配列の最初の要素になるはずです。

 この前提が正しいのは、ASP.NET 2.0を使用しているときです。ASP.NET 2.0の内部のRegisterArrayDeclaration(arrayName, arrayValue)メソッドでは、ListDictionaryオブジェクトに配列要素を格納してから、それらの要素をクライアントサイドの配列にレンダリングするからです。ListDictionaryはFIFO(First In, First Out)で動作するので、要素はサーバーサイドコードで追加した順序でクライアントサイド配列に格納されます。

 ただし、ASP.NET 1.xを使用していると、RegisterArrayDeclaration(arrayName, arrayValue)の実装でHybridDictionaryが使われます。HybridDictionaryでは、最初にListDictionaryを使って項目が保存されますが、要素が一定の数を超えると(具体的には9番目の要素から)Hashtableが使われます。Hashtableの要素は、ハッシュ値に基づく順序で返されるため、必ずしもプログラムで追加した順序と同じではありません。この問題を回避するには、RegisterArrayDeclarationメソッドのロジックを独自の方法(素のJavaScriptそのものを吐き出すなど)で置き換えるか、Peter BlumのフリーのRegisterScriptsライブラリを使います。HybridDictionaryの順序の問題と使用可能な迂回策については、記事『Specialized Collections』を参照してください。

まとめ

 この記事では、クライアントサイドのテクニックを使ってGridViewのヘッダーに[Check/Uncheck All]チェックボックスを追加して、すべての下位チェックボックスを一度にオンまたはオフにする機能を用意する手順を説明しました。[Check All]ボタンと[Uncheck All]ボタンに加えてヘッダーの[Check/Uncheck All]チェックボックスを用意することで、グリッドのすべてのチェックボックスをオンまたはオフにする複数の方法をユーザーに提供できます。クライアントサイドスクリプトを使ってチェックボックスのオン、オフを処理するので、このインターフェイスは応答速度が速くなります。

 それでは、ハッピープログラミング!

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

Scott Mitchell(Scott Mitchell)

http://www.4guysfromrolla.com/ScottMitchell.shtml

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/522 2006/08/17 00:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング