|
トップページ
Webビジネス
Eコマース
Webファイナンス
Webマーケティング
パブリック
Webテクノロジー
携帯・ワイヤレス
Linux Today
Linux Tutorial
Thin Planet.jp
転職求人情報サイト
エンジニアの転職
紹介予定派遣の仕事
今日のヘッドライン
週間ヘッドライン
フォトコミュニティ
ストックフォト
クリップアート
イラスト
フェリカ
Web2.0
写真
イベントカレンダー
投資セミナー
新規登録
変更・解除
オプトインメールの登録・変更・解除
パートナーサイト
新築マンション
新築一戸建て
転職支援・適職紹介
アルバイト
独立・開業・起業
ストックフォト
イラスト
ネットストリート
旅行検索・旅行計画
オリジナルTシャツ
家具 インテリア
シミュレーション
コンテスト
トランクルーム
会社案内(地図)
グループ会社
株式会社アエリア
株式会社Ajax Net
株式会社エアネット
株式会社ゲームポット
お問い合わせ
広告掲載について
リンクについて
著作権について
その他のお問い合わせ
利用規約
プライバシーポリシー
人材募集
デベロッパー 2006年8月29日 10:00
デベロッパー・バックナンバー
クライアントサイドスクリプトを使ってGridView上のすべてのチェックボックスをオンにする方法
著者: Scott Mitchell オリジナル版を読む プリンター用 記事を転送
▼2006年8月29日 10:00 付の記事
■海外internet.com発の記事
サンプルファイル
はじめに
先週の記事『GridView上のすべてのチェックボックスをオンにする方法』では、1個のボタンのクリックでGridView上のすべてのチェックボックスをオンまたはオフにする機能を追加する方法を説明しました。この機能を実現するにはサーバーサイドコードを使う方法と、クライアントサイドスクリプトを使う方法の2つがあり、両方について詳しく解説しました。どちらのバージョンでも、ページには2個のボタン――「すべて選択(Check All)」と「すべて選択解除(Uncheck All)」――が配置され、これをクリックするとすべてのチェックボックスがオンまたはオフになります。サーバーサイドコードを使うバージョンでは、どちらのボタンをクリックしてもポストバックが発生し、プログラムによってすべてのチェックボックスのオンまたはオフが実行されます。クライアントサイドのバージョンでは、チェックボックスのオン/オフは短いJavaScriptコードで処理されます。
今回の記事では、このユーザーインターフェイスを改良し、クライアントサイドスクリプトを利用して、GridViewのチェックボックス(CheckBox)列の上にあるヘッダー行に[すべて選択/選択解除(Check/Uncheck All)]チェックボックスを用意することにします(次のスクリーンショットを参照)。このヘッダーのチェックボックスをオンにするとGridView上のすべてのチェックボックスがオンになり、逆にこれをオフにするとGridView上のすべてのチェックボックスがオフになります。この機能を追加するのは最初に考えていたよりも少しトリッキーな作業で、ちょっとした工夫が必要でした。この記事では、そういった問題点と、それを解決するために使った迂回策について詳細に見ていきます。それでは説明に移ります。
前回の記事『GridView上のすべてのチェックボックスをオンにする方法』をまだ読んでいなければ、先に進む前に目を通しておいてください。
[Check/Uncheck All]チェックボックスをヘッダーに追加する
このユーザーインターフェイスを実装する最初のステップでは、チェックボックス列のヘッダーに[Check/Uncheck All]チェックボックスを追加します。GridView上のチェックボックス列はTemplateFieldとして実装したので、ヘッダーにCheckBoxを追加するのに必要な作業は、次のようにTemplateFieldにHeaderTemplateを追加することだけです(簡潔にするため、GridViewのフォーマット関連の設定は一部省略しました)。
<asp:GridView ID="FileList" runat="server"
AutoGenerateColumns="False" DataKeyNames="FullName">
<Columns>
<asp:TemplateField>
<HeaderTemplate>
<asp:CheckBox runat="server" ID="HeaderLevelCheckBox" />
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox runat="server" ID="RowLevelCheckBox" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Name" HeaderText="Name" />
... Remaining BoundFields ...
</Columns>
</asp:GridView>
このコードを追加すると、チェックボックス列のヘッダーにCheckBoxが配置されますが、このヘッダーのCheckBoxをクリックしても何も起こりません。ヘッダーのCheckBoxをオンにするとグリッド内のすべてのCheckBoxがオンになり、同様にヘッダーのCheckBoxをオフにするとグリッド内のすべてのCheckBoxがオフになるような仕組みが必要です。また、オン/オフの反応速度を改善するために、この処理を完全にクライアントサイドでJavaScriptを使って行うことも必要です。
「GridView上のすべてのチェックボックスをオンにする方法」では、JavaScript関数ChangeAllCheckBoxStates(checkState)を詳しく見ていきました。この関数は、checkState入力パラメータの値に基づいてグリッド上のすべてのCheckBoxをオンまたはオフにします。前回の記事で紹介したクライアントサイドのデモの場合は、この関数を[Check All]ボタンまたは[Uncheck All]ボタンから呼び出し、その際にcheckState入力パラメータに値true([Check All]の場合)またはfalse([Uncheck All]の場合)を渡していました。今回まず考えたのは、このJavaScript関数をヘッダーのCheckBoxで再利用することでした。つまり、ヘッダーのCheckBoxのクライアントサイドonclickイベントでChangeAllCheckBoxStatesを呼び出し、checkStateパラメータにthis.checkedを渡すというものです。
この処理を行うために、Page_Loadイベントハンドラで以下のサーバーサイドコードを使用して、ヘッダーのCheckBoxのクライアントサイドonclickイベントを関連付けました。
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
Dim dirInfo As New DirectoryInfo(Request.PhysicalApplicationPath)
FileList.DataSource = dirInfo.GetFiles()
FileList.DataBind()
End If
’On every page visit we need to build up the CheckBoxIDs array
’Get the header CheckBox
Dim cbHeader As CheckBox = _
CType(FileList.HeaderRow.FindControl( _
"HeaderLevelCheckBox"), CheckBox)
’Run the ChangeCheckBoxState client-side function whenever the
’header checkbox is checked/unchecked
cbHeader.Attributes("onclick") = _
"ChangeAllCheckBoxStates(this.checked);"
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)
’Add the CheckBox’s ID to the client-side CheckBoxIDs array
ClientScript.RegisterArrayDeclaration( _
"CheckBoxIDs", String.Concat("’", cb.ClientID, "’"))
Next
End Sub
Page_Loadイベントハンドラの太字ではない部分は、前回の記事からそのままコピーしたコードです。最初の部分では、ページが最初に表示されたときにデータをGridViewにバインドします(それ以降のポストバックではこのバインドを行いません)。For Eachループの最後では、CheckBoxIDsクライアントサイド配列を作成します。この配列は、ChangeAllCheckBoxStates関数ですべてのグリッドのCheckBoxのオンまたはオフを行うときに、反復処理の対象となります。今回、[Check/Uncheck All]ヘッダーのCheckBoxをサポートするために追加したのが太字の部分です。特に、GridViewのHeaderRowのコントロールコレクションを検索してIDが"HeaderLevelCheckBox"のコントロールを見つけ、ヘッダーのCheckBoxへの参照を取得する部分に注目してください("HeaderLevelCheckBox"は、前述の宣言構文で宣言したヘッダーのCheckBoxのID値です)。
ヘッダーのCheckBoxへの参照を取得したら、次にクライアントサイドのonclickイベントハンドラでChangeAllCheckBoxStates関数が呼び出されるようにします。そのためには、CheckBoxのAttributesコレクションのonclick設定にChangeAllCheckBoxStates関数の呼び出しを割り当て、パラメータとしてthis.checkedを渡します。Attributesコレクションは、コントロールの外観となるHTMLに追加の属性値を指定するための手段です。クライアントサイドのHTML属性の操作とサーバーサイドASP.NETコードの使用方法については、記事『Working with Client-Side Script』を参照してください。
このコードを追加したことにより、ヘッダーのCheckBoxがオンになるとChangeAllCheckBoxStates(true)が呼び出されてグリッド上のすべてのCheckBoxがオンになり、逆にヘッダーのCheckBoxがオフになるとChangeAllCheckBoxStates(false)が呼び出されてすべてのCheckBoxがオフになります。
問題1
以上の変更を行った後に最初に気がついた問題は、ページ上の[Check All]ボタンや[Uncheck All]ボタンをクリックしても、ヘッダーのCheckBoxがオンまたはオフにならないことでした。グリッド上の他のCheckBoxは、それまでどおり正しくオン、オフされます。原因は、この2つのボタンはChangeAllCheckBoxStates関数を呼び出しており、ChangeAllCheckBoxStates関数は、CheckBoxIDs配列だけを反復処理して、この配列に登録されたすべてのCheckBoxをオンまたはオフにしているからです。ヘッダーのCheckBoxはこの配列に含まれないため、ChangeAllCheckBoxStates関数を呼び出してもオン/オフの状態は以前と変わりません(もちろん、ヘッダーのCheckBoxを直接オン/オフするときはこの問題は起こりません。ユーザーの操作によってCheckBoxのオン/オフが適切に処理されるからです)。
この問題を修正するため、単純な方法ですが、ヘッダーのCheckBoxをCheckBoxIDs配列内のIDリストに加えました。この追加処理は、Page_Loadイベントハンドラ内でヘッダーのCheckBoxのAttributes("onclick")プロパティを設定した直後に行います。以下にそのコードを示します。
’Add the CheckBox’s ID to the client-side CheckBoxIDs array
ClientScript.RegisterArrayDeclaration( _
"CheckBoxIDs", String.Concat("’", cbHeader.ClientID, "’"))
ヘッダーのCheckBoxのIDを配列に追加すると、ユーザーが[Check All]ボタンと[Uncheck All]ボタンをクリックしたときに、ヘッダーのCheckBoxがグリッド上の下位のCheckBoxと共に正しくオンまたはオフになります。
問題2
ヘッダーのCheckBoxをオンにすると、グリッド上のすべてのチェックボックスがオンになるのですから、当初私は、ヘッダーのCheckBoxは一定のアクション(具体的に言うと、グリッド上のすべての下位チェックボックスをオンにするアクション)を単独で実行するユーザーインターフェイス項目であると考えていました。しかし実際には、ヘッダーのCheckBoxは、グリッド上のチェックボックスの状態を反映しているに過ぎません。つまり、ヘッダーのCheckBoxがオンになっていれば、グリッド上のすべての他のチェックボックスもオンになっていることを意味します。ヘッダーチェックボックスがオフになっていれば、グリッド上のチェックボックスの1個以上がオフになっています。
このような事情を勘案すれば、グリッド上の他のチェックボックスがすべて手動でオンにされたときにヘッダーチェックボックスが自動的にオンになるような仕組みが必要なことは明らかです。またその反対に、その他のすべてのチェックボックスがオンにされた後でその1個が手動でオフにされた場合は、ヘッダーチェックボックスが自動的にオフになる必要もあります。この仕組みを実現するため、次のように修正することにしました。
ChangeHeaderAsNeeded()というJavaScript関数を追加し、この関数の中で、グリッド上の他のCheckBoxがすべてオンの場合はヘッダーのCheckBoxをオンにし、オフのCheckBoxが1個でもある場合はヘッダーのCheckBoxをオフにする。
下位の各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]チェックボックスを用意することで、グリッドのすべてのチェックボックスをオンまたはオフにする複数の方法をユーザーに提供できます。クライアントサイドスクリプトを使ってチェックボックスのオン、オフを処理するので、このインターフェイスは応答速度が速くなります。
それでは、ハッピープログラミング!
著者紹介
Scott Mitchell(Scott Mitchell)
http://www.4guysfromrolla.com/ScottMitchell.shtml
関連記事
CreateUserWizardコントロールのマルチステッププロセス化
GridView上のすべてのチェックボックスをオンにする方法
ASP.NET 2.0のHTTPハンドラ(*.ashx)をデバッグする
ASP.NET 2.0でカスタムのページング処理と並び替えを併用する
不快感を与えるテキストデータの入力を排除する
users
users
★最新トップニュース
■ EMC、子会社 VMware の IPO 価格を引き上げ(8月11日 12:00)
EMC は来週にも、仮想化技術子会社 VMware の新規株式公開 (IPO) を実施する。同社は VMware 株の売出見通し価格を27ドルないし29ドルへと引き上げた。
■ Microsoft、8月の月例更新で9件のセキュリティ情報を公開予定(8月11日 12:00)
Microsoft が、14日に予定している8月の月例更新について、先行情報を発表した。公開予定のセキュリティ情報は9件と多めの内容だ。
■ ソフトバンク、「S! ケータイ動画」の提供終了を発表(8月10日 18:30)
ソフトバンクモバイルは、2007年8月10日、ソフトバンク 3G 携帯電話向け大容量動画配信サービス「S! ケータイ動画」を、同年9月30日をもって終了することを発表した。
■ ソフトバンク、「S! キャスト」「3G お天気アイコン」の提供を終了(8月10日 18:20)
ソフトバンクモバイルは、2007年8月10日、「S! キャスト」および「3G お天気アイコン」の提供を同年9月28日に終了することを発表した。
■ IP PBX の ASP サービスで OSS Asterisk を採用、「Nokia E61」に対応(8月10日 18:00)
同時呼出機能を追加、携帯電話や自宅の電話、会社など、同時に3か所まで一斉に着信できるようになった。
IT系の求人情報【毎週水曜更新】
スカウトに登録する
デイリーリサーチ / DLサイト
OnlineResearchPortal (リサーチデータバンク)
アンカーリサーチ with goo
モバイルリサーチ with goo
10月24日開催『アウンコンサルティングの「すぐできるSEO」』-基本から応用まで-
募集を締め切りました。多数のご応募ありがとうございました。
DevX
15 seconds
4 Guys From Rolla
CodeGuru
アクセス解析で学ぶデータ分析マーケティング
【アクセス解析の次の一手】アクセス解析ツールを理解する(8月10日)
IT マネジメント
管理職に IT 部門が教えるべき10の話(8月10日)
百式のネットビジネス研究
10代のドライバーに特化した保険サービス「Teensurance」(8月10日)
週刊-サイト別アクセス状況データ
ビデオリサーチインタラクティブ調査(週刊サイト別アクセス状況データ) (8月9日)
IM にみるビジネスコミュニケーション
IM が変える未来のコミュニケーション(8月9日)
サーチテリアのモバイルリスティング
「あえて」ランディングページをはずしてみる(8月8日)
Eメールマーケティング事情
効果が出るメールは5つのルールを実践している!(8月8日)
アイレップのSEMフロンティア
コンバージョン率に直結するフォームの入力性(8月7日)
エンジニア転職ノウハウ開発室
今はもう通わない心と心…部下から上司へ7通の手紙(8月7日)
SNSをビジネスに活用しよう
第五十七回 「コントロール&コラボレーション Enterprise 2.0の機運」(8月7日)
転職徒然草
深夜の模擬面接(8月6日)
サーチからはじまるインタラクティブエージェンシー
コンシューマーの心の扉を開く「鍵」~クロスメディア戦略のポイントをさぐる(8月6日)
セキュリティチャネル
テレコムチャネル
サーチエンジンウォッチ
海外のインターネットコム アメリカ|韓国|ドイツ|トルコ
Copyright 2007 Jupitermedia Corporation All Rights Reserved.
最近のコメント