GridViewのフッターを使用したレコード追加について

タグの編集
投稿者 ASP.NET初心者  (社会人) 投稿日時 2020/2/25 10:24:07
お世話になります。初めて投稿させて頂きます。
GridViewへSQLServerデータをバウンドし修正、削除といった動きは実現出来ています。
新規に最下行よりレコードを追加する機能を組み込みたいので、テンプレートにてフッターを用意し
テキストボックスやチェックボックスを配置しました。
フッター上のボタンをクリックした時に
For Each key As String In Request.Form.AllKeys
    If key.Contains("フッター上のテキストボックス") Then
        SqlDataSource.InsertParameters.Add(New ControlParameter("DB項目", TypeCode.Int32, key, "Text"))
    End If
    If key.Contains("フッター上のチェックボックス") Then
        SqlDataSource.InsertParameters.Add(New ControlParameter("DB項目", TypeCode.Boolean, key, "Checked"))
    End If

以下、画面項目数分列挙

Next
SqlDataSource.Insert()
といったコーディングをしました。
全ての項目を入力し、チェックボックスもOnにした場合はレコードが追加されます。
テキストボックスを未入力にした場合も値=Nullで追加されます。
しかし、チェックボックス未選択の状態では先のkey.Containsにチェックボックスのキーが取得出来ずInsertが異常終了します(メッセージ=スカラー変数"@DB項目名"を宣言してください)
何か根本的な作法が間違っているのでしょうか?よろしくお願いします。
DB側の問題ではないと思っておりますが、DB上のチェックボックス項目はBit、Nullを許可しております。
投稿者 るきお  (社会人) 投稿日時 2020/2/25 23:09:33
しかとは確認していませんが、Request.Form.AllKeysに値が設定されるかどうかはブラウザーが値を送信するかどうかなので、チェックしていないチェックボックスはそもそも値を送信してくれないのかもしれません。
これは間違っているかもしれませんが、どちらにしてもRequest.Form.AllKeysを使って通常のロジックを書くことはよろしくなく、テキストボックスやチェックボックスの値を取得するにはTextプロパティやCheckプロパティを使用するべきです。

GridViewのFooterRowプロパティでFindControlすると、フッターに配置してあるコントロールに直接アクセスできます。
※フッターに限らずGridView内に配置されたコントロールにプログラムからアクセスするにはこのような階層構造を利用します。
下記サンプルは値の取得までですが、ここまでできれば更新処理は別問題ですよね。

VB
Public Class WebForm1
    Inherits System.Web.UI.Page

    Protected Sub GridView1_RowCommand(sender As Object, e As GridViewCommandEventArgs) Handles GridView1.RowCommand

        If e.CommandName = "AddNew" Then
            Dim xId As String = DirectCast(GridView1.FooterRow.FindControl("txtFooterXID"), TextBox).Text
            Dim xName As String = DirectCast(GridView1.FooterRow.FindControl("txtFooterXName"), TextBox).Text
            Dim xBit As Boolean = DirectCast(GridView1.FooterRow.FindControl("txtFooterXBit"), CheckBox).Checked

            MsgBox(String.Format("xId={0}, xName={1}, xBit={2}", xId, xName, xBit))
        End If

    End Sub
End Class

Public Class DataBaseReader

    Public Function OpenData() As DataTable
        Dim table As New DataTable
        table.Columns.Add("XID"GetType(Integer))
        table.Columns.Add("XName"GetType(String))
        table.Columns.Add("XBit"GetType(Boolean))

        table.Rows.Add(1, "徳川家康"True)
        table.Rows.Add(2, "織田信長"False)
        table.Rows.Add(3, "豊臣秀吉"False)

        Return table
    End Function
End Class


長くなるので回答を分割します。

投稿者 るきお  (社会人) 投稿日時 2020/2/25 23:10:24
続きです。

ASP.NET
<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="WebForm1.aspx.vb" Inherits="WebApplication26.WebForm1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <br />
            <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataSourceID="ObjectDataSource1" ShowFooter="True">
                <Columns>
                    <asp:TemplateField>
                        <EditItemTemplate>
                            <asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("XID") %>'></asp:TextBox> 
                        </EditItemTemplate>
                        <FooterTemplate>
                            <asp:TextBox ID="txtFooterXID" runat="server" Text='<%# Bind("XID") %>'></asp:TextBox> 
                        </FooterTemplate>
                        <ItemTemplate>
                            <asp:Label ID="Label1" runat="server" Text='<%# Bind("XID") %>'></asp:Label> 
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField>
                        <EditItemTemplate>
                            <asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("XName") %>'></asp:TextBox> 
                        </EditItemTemplate>
                        <FooterTemplate>
                            <asp:TextBox ID="txtFooterXName" runat="server" Text='<%# Bind("XName") %>'></asp:TextBox> 
                        </FooterTemplate>
                        <ItemTemplate>
                            <asp:Label ID="Label2" runat="server" Text='<%# Bind("XName") %>'></asp:Label> 
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField>
                        <EditItemTemplate>
                            <asp:CheckBox ID="CheckBox1" runat="server" Checked='<%# Bind("XBit") %>' /> 
                        </EditItemTemplate>
                        <FooterTemplate>
                            <asp:CheckBox ID="txtFooterXBit" runat="server" Checked='<%# Bind("XBit") %>' Enabled="true" /> 
                            &nbsp;<asp:Button ID="Button2" runat="server" Text="登録" CommandName="AddNew" />
                        </FooterTemplate>
                        <ItemTemplate>
                            <asp:CheckBox ID="CheckBox1" runat="server" Checked='<%# Bind("XBit") %>' /> 
                        </ItemTemplate>
                    </asp:TemplateField>
                </Columns>
                
            </asp:GridView>
        </div>
        <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="OpenData" TypeName="WebApplication26.DataBaseReader"></asp:ObjectDataSource>
    </form>
</body>
</html>


SQL Serverを使うのが面倒だったのでObjectDataSourceを使ってプログラム内だけで完結させました。
回答する前にこのサンプルを作る必要があったので手間がかかりました。(途中で止めようかと思ってしまいました。)
できましたら、手軽に試せるサンプルつきで質問していただけると助かります。
投稿者 ASP.NET初心者  (社会人) 投稿日時 2020/2/26 08:47:48
回答ありがとうございます。
ひとまず、ご教授頂いた方法で値の取得が出来るところまでは確認出来ました。
おっしゃる通り更新は別問題ですが、これから試したいと思います。
感謝いたします。今後はなるべくソース全体を記載するように致します。
投稿者 るきお  (社会人) 投稿日時 2020/2/29 11:20:16
ASP.NET初心者さんが使用されている ASP.NETのWebフォームは 2019年にリリースされた.NET Framework 4.8に含まれているものが最後のバージョンで、今後は『過去のもの』という扱いになって行きますのでご注意ください。

新しくWebアプリケーションを作成されるのであればASP.NET Core MVCまたはASP.NET Core Blazorをお勧めします。

私としてはBlazorを本格的に利用するのはもう少し様子を見てからにしたく、今使うならASP.NET Core MVC系を選択します。

何年も使うわけではなく、ちょっとした簡単なアプリを手早く作りたいのであれば、ASP.NET Webフォームを含めて好きなフレームワークを使用していただいて問題ありません。
投稿者 ASP.NET初心者  (社会人) 投稿日時 2020/3/2 13:50:04
今々は簡単なプログラムしか考えておりませんのでWebフォームのままで進めていますが、やはりASP.NETもMVCなのですね。簡単なプログラムで済むものはMVCを避けていましたが、いずれ通らなければならない知識と認識しました。ご助言、ありがとうございます。