| デベロッパー | 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関数 この処理を行うために、 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 ヘッダーのCheckBoxへの参照を取得したら、次にクライアントサイドのonclickイベントハンドラで このコードを追加したことにより、ヘッダーのCheckBoxがオンになると 問題1 以上の変更を行った後に最初に気がついた問題は、ページ上の[Check All]ボタンや[Uncheck All]ボタンをクリックしても、ヘッダーのCheckBoxがオンまたはオフにならないことでした。グリッド上の他のCheckBoxは、それまでどおり正しくオン、オフされます。原因は、この2つのボタンは この問題を修正するため、単純な方法ですが、ヘッダーのCheckBoxをCheckBoxIDs配列内のIDリストに加えました。この追加処理は、 ’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個が手動でオフにされた場合は、ヘッダーチェックボックスが自動的にオフになる必要もあります。この仕組みを実現するため、次のように修正することにしました。
まずは 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イベントの発生時に 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が常に最初にあると前提しても安全か? この前提が正しいのは、ASP.NET 2.0を使用しているときです。ASP.NET 2.0の内部の ただし、ASP.NET 1.xを使用していると、 まとめこの記事では、クライアントサイドのテクニックを使ってGridViewのヘッダーに[Check/Uncheck All]チェックボックスを追加して、すべての下位チェックボックスを一度にオンまたはオフにする機能を用意する手順を説明しました。[Check All]ボタンと[Uncheck All]ボタンに加えてヘッダーの[Check/Uncheck All]チェックボックスを用意することで、グリッドのすべてのチェックボックスをオンまたはオフにする複数の方法をユーザーに提供できます。クライアントサイドスクリプトを使ってチェックボックスのオン、オフを処理するので、このインターフェイスは応答速度が速くなります。 それでは、ハッピープログラミング! 著者紹介Scott Mitchell(Scott Mitchell)
|