none
GridViewの入れ子のデータ取得とヘッダー行の追加について RRS feed

  • 質問

  • GridViewの入れ子のデータ取得とヘッダー行の追加について教えて下さい。

    ・GridViewの入れ子のデータ取得
    以下のようにGridViewの中にGridViewを入れ子にしています。
    内側のGV2のRowDataBoundイベント時にHF1のデータを取得したいと思っていますが、
    オブジェクトの参照ができないようでエラーになります。どのように記述すれば
    データを取得できるのでしょうか?(プログラムは、一部省略しています)

            <asp:GridView ID="GV1" runat="server">
                <Columns>
                    <asp:TemplateField>
                        <ItemTemplate>
                            <asp:HiddenField ID="HF1" runat="server" Value='<%# Eval("C_Date") %>' />
                            <asp:GridView ID="GV2" runat="server" AutoGenerateColumns="False" DataSourceID="ODS2" OnRowDataBound="GV2_RowDataBound">
                                <Columns>
                                    <asp:BoundField DataField="User" HeaderText="名前" />
                                    <asp:BoundField DataField="Col_1" HeaderText="1" />
                                    <asp:BoundField DataField="Col_2"  HeaderText="2" />
                                    <asp:BoundField DataField="Col_3" HeaderText="3" />
                                    <asp:BoundField DataField="Col_4" HeaderText="4" />
                                </Columns>
                            </asp:GridView>
                            <asp:ObjectDataSource ID="ODS2" runat="server">
                                <SelectParameters>
                                    <asp:ControlParameter ControlID="HF1" />
                                </SelectParameters>
                            </asp:ObjectDataSource>
                        </ItemTemplate>
                    </asp:TemplateField>
                </Columns>
            </asp:GridView>

    ・ヘッダー行の追加
    ヘッダーが「名前 1 2 3 4」となりますが、このヘッダーの2行目に
    行を追加して2行にしたいと思っています。どのように記述すれば追加できるのでしょうか?
    「名前 1 2 3 4」
    「   月 火 水 木」

    以下のようにすれば、元のヘッダーの上に追加することはできましたが、下の行に
    追加しようとAddAt(1, row1)に変更すればエラーになってしまいます。
        Protected Sub GV2_RowCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
            Dim row1 As New GridViewRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal)
            '挿入したい行を追加処理 月 火 水 木
            sender.Controls(0).Controls.AddAt(0, row1)
        End Sub

    すみませんが、ご指導よろしくお願いします。


    2011年4月17日 14:25

回答

  • > 「指定された引数は、有効な値の範囲内にありません。
    > パラメーター名: index」です。

    それは CType(sender, GridView).Controls(0).Controls に Control が
    ない状態で、インデックス 1 の位置に Control を追加しようとしたから
    でしょう。

    RowCreated ではなくて RowDataBound イベントのハンドラで行えばうま
    くいくと思います。

    ただし、それでうまくいっても、ポストバックで表示が崩れるかもしれま
    せん。その場合は、GridView の EnableViewState を False にしてみて
    ください。(そのような問題があるから ListView の使用をお勧めしたの
    ですが)


    > ODS2 の Selecting イベントで取得できましたが、なぜ以下のような記
    > 述で無理なのでしょうか?

    Selecting イベントと RowDataBound イベントはどちらが早く発生するか、
    パラメータはどのタイミングで渡す必要があるかを考えましょう。

    2011年4月18日 11:49

すべての返信

  • > ・GridViewの入れ子のデータ取得

    HiddenField ではデータは渡せません。

    ODS2 の Selecting イベントでデータを渡すことができると思い
    ます。

    > ・ヘッダー行の追加

    ヘッダーだけでなく、データの行も 2 行にしたいなら、ListView
    を使うことをお勧めします。

    GridView で 1 レコードを複数行に入れるのはできないと思った方
    がいいです(できないことはないかもしれませんが、面倒ですし、
    解決できない問題があります)。

     

    2011年4月17日 16:05
  • 追伸です。

    ヘッダーだけ 2 行にしたいなら何とかなると思います。エラーが
    出るのは sender をキャストしてないからではないですか?

    2011年4月17日 16:27
  • 返信ありがとうございます。

    ヘッダーだけ2行にします。イメージは以下のようにカレンダーにユーザーの状況を表示したいと思っています。

             1  2  3  4  5 ・・・

             月 火 水 木 金

    A男           ○     ○  

    B子          ○     ×

    >ヘッダーだけ 2 行にしたいなら何とかなると思います。エラーが
    >出るのは sender をキャストしてないからではないですか?

    質問時のエラーに間違いがありました。
    「指定された引数は、有効な値の範囲内にありません。
    パラメーター名: index」です。

    CType(sender, GridView).Controls(0).Controls.AddAt(0, row1) では、ヘッダーの上に追加
    曜日は、日付の下に表示したいため
    CType(sender, GridView).Controls(0).Controls.AddAt(1, row1)  で、エラーになります。

    >ODS2 の Selecting イベントでデータを渡すことができると思い
    >ます。
    ODS2 の Selecting イベントで取得できましたが、なぜ以下のような記述で無理なのでしょうか?
        Protected Sub GV2_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
            If e.Row.RowType = DataControlRowType.DataRow Then
                Dim DateGet As Date = CDate(CType(GV1.FindControl("HF1"), HiddenField).Value)

            End If
        End Sub

    よろしくお願いします。

     



    2011年4月18日 3:05
  • > 「指定された引数は、有効な値の範囲内にありません。
    > パラメーター名: index」です。

    それは CType(sender, GridView).Controls(0).Controls に Control が
    ない状態で、インデックス 1 の位置に Control を追加しようとしたから
    でしょう。

    RowCreated ではなくて RowDataBound イベントのハンドラで行えばうま
    くいくと思います。

    ただし、それでうまくいっても、ポストバックで表示が崩れるかもしれま
    せん。その場合は、GridView の EnableViewState を False にしてみて
    ください。(そのような問題があるから ListView の使用をお勧めしたの
    ですが)


    > ODS2 の Selecting イベントで取得できましたが、なぜ以下のような記
    > 述で無理なのでしょうか?

    Selecting イベントと RowDataBound イベントはどちらが早く発生するか、
    パラメータはどのタイミングで渡す必要があるかを考えましょう。

    2011年4月18日 11:49
  • >RowCreated ではなくて RowDataBound イベントのハンドラで行えばうま
    >くいくと思います。

    変更したところ表示できるようになりました。ありがとうございます。

    >Selecting イベントと RowDataBound イベントはどちらが早く発生するか、
    >パラメータはどのタイミングで渡す必要があるかを考えましょう。
    Selecting イベントのほうが早く発生します。パラメータは,Selecting イベント時だと思います。
    GV2_RowDataBoundイベント時には、パラメータも渡し終わり、HF1にもデータが渡っているように
    思っています。HF1にもデータが渡っているからこそ、GV2_RowDataBoundイベントで表が生成されていると思っています。
    すみませんが、間違っている点をもう少し教えていただけませんでしょうか?

    2011年4月18日 12:31
  • > GV2_RowDataBoundイベントで表が生成されていると思っています。

    よく分かりませんが、目的の表が生成されたんですか? だったら、
    質問する必要はなくて、それでよろしいのでは。

    2011年4月18日 14:16
  • >よく分かりませんが、目的の表が生成されたんですか?

    お陰様で目的の表が生成できました。ありがとうございます。

    ただ、なぜ

        Protected Sub GV2_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
            If e.Row.RowType = DataControlRowType.DataRow Then
                Dim DateGet As Date = CDate(CType(GV1.FindControl("HF1"), HiddenField).Value)

            End If
        End Sub

    の記述で駄目なのか知りたいと思っています。

     

    2011年4月19日 11:01
  • > ただ、なぜ
    >
    > Protected Sub GV2_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
    >     If e.Row.RowType = DataControlRowType.DataRow Then
    >         Dim DateGet As Date = CDate(CType(GV1.FindControl("HF1"), HiddenField).Value)
    >     End If
    > End Sub
    >
    > の記述で駄目なのか知りたいと思っています。

    先に「GV2_RowDataBoundイベントで表が生成されている」と書いて
    あったので、上記のコードでうまくいったと思ったいましたが、違
    うようですね。

    断片的なコードからでははっきり分かりませんが・・・

    抽出の条件に使うパラメータ (C_Date ですか?) は HF1 を介して
    ObjectDataSource.SelectMethod に設定したメソッドに渡し、それ
    から DB にクエリを投げてデータを取得しようとしているのですよ
    ね。

    クエリを投げるとき(Selecting イベント)にパラメータが必要な
    のに、それより後のタイミング(RowDataBound イベント)で HF1
    からパラメータを取得しても手遅れではないのですか?

    2011年4月19日 13:26
  • SurferOnWww様。

    いつもご回答ありがとうございます。

    >抽出の条件に使うパラメータ (C_Date ですか?) は HF1 を介して
    >ObjectDataSource.SelectMethod に設定したメソッドに渡し、それ
    >から DB にクエリを投げてデータを取得しようとしているのですよ
    >ね。

    そうです。

    >クエリを投げるとき(Selecting イベント)にパラメータが必要な
    >のに、それより後のタイミング(RowDataBound イベント)で HF1
    >からパラメータを取得しても手遅れではないのですか?

    当初、以下のプログラムで HF1の年月を取得し、月によって替わる最終日(28~31日)の列を表示、非表示に変更しようとし、なぜ取得

    できないのか疑問に思ったためです。ただ、お陰様で、Selecting イベントで取得でき、目的の表が表示されています。

       Protected Sub GV2_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
            If e.Row.RowType = DataControlRowType.DataRow Then
                Dim DateGet As Date = CDate(CType(GV1.FindControl("HF1"), HiddenField).Value)

            End If
        End Sub

    2011年4月20日 10:33