skip to Main Content

I am aiming to get data:

  • From an sql database
  • To a gridview
  • To a local table

So far, I am able to use a stored procedure to display the sql data to a gridvew and I am also able to use checkboxes to send the data to a local table.

Issue:
Only one row’s data is being submitted to the table, despite the number of checkboxes checked.

ex. I click 3 checkboxes, wanting to get 3 different rows of data to the table. I hit the submit button and when I check the table, only one of the "checked" rows is submitted to the table 3 times.

EDITED Code:

protected void btnSubmit_Click(object sender, EventArgs e)
    {
        string connectionString = ConfigurationManager.ConnectionStrings["localDataB"].ConnectionString;

        using (var sqlConnection = new SqlConnection(connectionString))
        {
            sqlConnection.Open();

            string insertStatement = "INSERT into LocalDB (Item1, Item2, Item3)" + "(@Item1, @Item2, @Item3)";

            string Data1, Data2;
            float Data3;

            foreach (GridViewRow gRow in GridView1.Rows)
            {

                CheckBox ckSel = (gRow.FindControl("checker") as CheckBox);
                if (ckSel.Checked)
                {
                    Data1 = Convert.ToString(gRow.Cells[1].Text);
                    Data2 = Convert.ToString(gRow.Cells[2].Text);
                    Data3 = Convert.ToInt32(gRow.Cells[3].Text);

                    using (var sqlCommand = new SqlCommand(insertStatement, sqlConnection))
                    {
                        sqlCommand.Parameters.Add("Item1", SqlDbType.Text).Value = Data1;
                        sqlCommand.Parameters.Add("Item2", SqlDbType.Text).Value = Data2;
                        sqlCommand.Parameters.Add("Item3", SqlDbType.Float).Value = Data3;
                        sqlCommand.ExecuteNonQuery();
                    }
                }
            }
        }
        GVbind();

Code for checkbox inside grid:

<asp:GridView ID="GridView1" runat="server" EmptyDataText="No Data Found" BackColor="#CCCCCC" BorderColor="#999999" BorderStyle="Solid" BorderWidth="3px" CellPadding="4"
            AutoGenerateColumns="False" CellSpacing="2" ForeColor="Black" DataKeyNames="Data1" Width="70%" Visible="False" ShowFooter="True">
            <Columns>
                <asp:TemplateField>
                    <HeaderTemplate>
                        <asp:Label ID="SelectBox" runat="server" Text="Select"></asp:Label>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:CheckBox ID="checker" runat="server" OnCheckedChanged="checker_CheckedChanged"/>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:BoundField DataField="Data1" HeaderText="Title1" ReadOnly="True" />
                <asp:BoundField DataField="Data2" HeaderText="Title2" ReadOnly="True" />
                <asp:BoundField DataField="Data3" HeaderText="Title3" />
            </Columns>
        </asp:GridView>

2

Answers


  1. It should be like this;

    sqlCommand.Parameters.AddWithValue("@Item1", data1);
    sqlCommand.Parameters.AddWithValue("@Item2", data2);
    sqlCommand.Parameters.AddWithValue("@Item3", data3);
    
    Login or Signup to reply.
  2. Ok, it not at all clear what your routine checker_CheckedChanged() does?

    You don’t need a post-back or anything for the check boxes – but ONLY the one submit button and code stub

    . Those data1, data2 etc. will NOT persist in memory anyway. So, you can’t use that routine – but you don’t need it either.

    Unless the grid has multiple pages etc., then dump that routine. You are free to check box any row in the grid. You then have one submit button code, and that routine just needs a bit of change to check all GV rows, and save the check box values.

    That submit button code thus can/will look like this:

        protected void btnSubmit_Click(object sender, EventArgs e)
        {
            string connectionString = ConfigurationManager.ConnectionStrings["localDataB"].ConnectionString;
    
            using (var sqlConnection = new SqlConnection(connectionString))
            {
                sqlConnection.Open();
    
                // insert any row with check boxes into temp db
    
                string insertStatement = "INSERT into LocalDB (Item1, Item2, Item3) " + 
                                         "values (@Item1, @Item2, @Item3)";
    
                bool Data1, Data2, Data3;
    
                foreach (GridViewRow gRow in GridView1.Rows)
                {
                    Data1 = Convert.ToBoolean(gRow.Cells[0].ToString());
                    Data2 = Convert.ToBoolean(gRow.Cells[1].ToString());
                    Data3 = Convert.ToBoolean(gRow.Cells[2].ToString());
    
                    // save data if ANY is checked
                    if (Data1 | Data2 | Data3)
                    {
                        using (var sqlCommand = new SqlCommand(insertStatement, sqlConnection))
                        {
                            sqlCommand.Parameters.Add("@Item1", SqlDbType.Bit).Value = Data1;
                            sqlCommand.Parameters.Add("@Item2", SqlDbType.Bit).Value = Data2;
                            sqlCommand.Parameters.Add("@Item3", SqlDbType.Bit).Value = Data3;
                            sqlCommand.ExecuteNonQuery();
                        }
                    }
                }
            }
        GVbind();
        }
    

    I don’t see the need for your first routine. The submit button can loop the GV, get the check box values, and if any one of the 3 is checked, then you do the insert.

    However, keep in mind that the cells[] collection ONLY works for datafields if you using a templated control and REAL check box, then you need to use findcontrol, and NOT the cells[] collection

    Edit:

    Ok, first, information provided suggests that a template field is being used.

    HOWEVER, we will first address the CheckBoxField code, since it HARD to google and find that answer. So I going to include that answer.

    If a check box is a datafield, then you can’t change/edit, but you STILL MAY want to iterate over the GV, and get those values.

    So, for data fields, say like this:

    <asp:CheckBoxField DataField="Active" HeaderText="Active" />
    

    Then our code has to work like this (you have to dig deeper into cells() colleciton.

    So, code becomes this:

              foreach (GridViewRow gRow in GridView1.Rows)
                {
                    Data1 =(gRow.Cells[0].Controls[0] as CheckBox).Checked;
                    Data2 = (gRow.Cells[1].Controls[0] as CheckBox).Checked;
                    Data3 = (gRow.Cells[2].Controls[0] as CheckBox).Checked;
    

    Note how a CheckBoxField requires us to use controls.

    However, as noted, with template field (any kind and ANY of them?).

    WE DO NOT use the Cells[] collection and templated columns DO NOT appear in the cells collection.

    And thus, in a lot (probably most) cases, then we can expect to have a CheckBox control dropped into the markup as a templated field.

    Typical looks like this:

           <asp:GridView ID="GridView1" runat="server" class="table borderhide" 
                AutoGenerateColumns="false" DataKeyNames="ID">
                <Columns>
                    <asp:BoundField DataField="FirstName"   HeaderText="FirstName"  />
                    <asp:BoundField DataField="LastName"    HeaderText="LastName"   />
                    <asp:BoundField DataField="City"        HeaderText="City"       />
                    <asp:BoundField DataField="HotelName"   HeaderText="HotelName" HeaderStyle-Width="200"   />
                    <asp:BoundField DataField="Description" HeaderText="Description" />
    
                    <asp:TemplateField HeaderText="Smoking"  ItemStyle-HorizontalAlign="Center"  >
                        <ItemTemplate>
                            <asp:CheckBox ID="chkSmoking" runat="server"
                                Checked='<%# Eval("Smoking") %>' />
                        </ItemTemplate>
                    </asp:TemplateField>
    
                    <asp:TemplateField HeaderText="Balcony"  ItemStyle-HorizontalAlign="Center"  >
                        <ItemTemplate>
                            <asp:CheckBox ID="chkBalcony" runat="server" 
                                Checked='<%# Eval("Balcony") %>' />
                        </ItemTemplate>
                    </asp:TemplateField>
    
                </Columns>
            </asp:GridView>
    

    So in above, the first values (bound fields) WILL BE found in cells colleciton.

    However, the templated fields above? we have to do this:

                               "WHERE ID = @ID";
                foreach (GridViewRow gRow in GridView1.Rows)
                {
                    CheckBox cSmoke = (CheckBox)gRow.FindControl("chkSmoking");
                    CheckBox cBlacony = (CheckBox)gRow.FindControl("chkBalcony");
                    int PKID = (int)GridView1.DataKeys[gRow.RowIndex]["ID"];
    
                    using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
                    {
                        cmdSQL.Parameters.Add("@S", SqlDbType.Bit).Value = cSmoke.Checked;
                        cmdSQL.Parameters.Add("@B", SqlDbType.Bit).Value = cBlacony.Checked;
                        cmdSQL.Parameters.Add("@ID", SqlDbType.Int).Value = PKID;
                        cmdSQL.ExecuteNonQuery();
                    }
                }
    

    So, our code then becomes this:

                foreach (GridViewRow gRow in GridView1.Rows)
                {
                    Data1 =(gRow.FindControl("Active") as CheckBox).Checked;
                    Data2 = (gRow.FindControl("Smoking") as CheckBox).Checked;
                    Data3 = (gRow.FindControl("Balcony") as CheckBox).Checked;
    

    Now of course, you replace the "Text control" id with YOUR data 1, 2, and 3 id that you used.

    The rest of the code should be the same.

    BIG LESSON OF THE DAY?

    Post a wee bit of markup – not a huge boatload – but just a few lines next time. You save world poverty, and I would have been able to post a better answer next time.

    So the rule is:

    DataBound fields – use cells[] collection.

    Templated fields – you have to using .FindControl("name of control id goes here")

    Edit#2

    Ok, so far, the question is now this:

    We have some data. If the user checks the row 1, or 5 or 10 rows, for each of the checked rows, I want to write out the columns/values I have in 3 other columns item1, item2, item3?

    Simple queston!!!!

    Ok, so the ONLY missing information is WHAT data type field type is item1, item2, and item3? We only really are missing that part.

    So, if check box = true, write out those 3 item columns to the new temp table.

    So, the code now should be:

                bool Data1, Data2, Data3;
    
                foreach (GridViewRow gRow in GridView1.Rows)
                {
                    // get check box - 
    
                    CheckBox ckSel = (gRow.FindControl("checker") as CheckBox);
    
                    // save data if ANY is checked
                    if (ckSel.Checked)
                    {
                        Data1 = Convert.ToBoolean(gRow.Cells[0].Text);
                        Data2 = Convert.ToBoolean(gRow.Cells[1].Text);
                        Data3 = Convert.ToBoolean(gRow.Cells[2].Text);
    
                        using (var sqlCommand = new SqlCommand(insertStatement, sqlConnection))
                        {
                            sqlCommand.Parameters.Add("@Item1", SqlDbType.Bit).Value = Data1;
                            sqlCommand.Parameters.Add("@Item2", SqlDbType.Bit).Value = Data2;
                            sqlCommand.Parameters.Add("@Item3", SqlDbType.Bit).Value = Data3;
                            sqlCommand.ExecuteNonQuery();
                        }
                    }
                }
    

    As noted, I stated MULTIPLE TIMES NOW, that non templated columns STILL MUST use cells collection. ONLY templated columns can and need to use FindControl. All others MUST continue to use .Cells[] collection.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search