1

What I am trying to do: I have 2 SQL Tables: discipline and program. In my gridview I want rows in discipline tables as column headers and rows of program table as row header. And inside the gridview there will be checkboxes corrosponding to a program and discipline filled in GridView1_RowDataBound method. For example:

An example of how the gridview looks

What is my Problem: When I click on the Submit Button, inside submit_click method, the if(cb.Checked) statement shows 'Object reference not set to an instance of an object.' error.

.aspx page:

    <div>
      <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" OnRowDataBound="GridView1_RowDataBound">
                <Columns>
                    <asp:BoundField DataField="Data" />
                </Columns>
      </asp:GridView>
    </div>
    <asp:Button ID="submit" OnClick="submit_Click" Text="Submit" runat="server" />
    <div runat="server" id="result"></div>

.aspx.cs page:

protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            DataSet disciplines = GetData("Select * From discipline"); //GetData gets Sql table and returns a DataSet
            DataSet programs = GetData("Select * from program");

            DataTable dt = new DataTable();
            dt.Columns.Add("Data");

            for (int i = 0; i < programs.Tables[0].Rows.Count; i++)
            {
                DataRow dr = dt.NewRow();
                dr[0] = programs.Tables[0].Rows[i]["PROG_DESC"];
                dt.Rows.Add(dr);
            }

            for (int i = 0; i < disciplines.Tables[0].Rows.Count; i++)
            {
                TemplateField tf = new TemplateField();
                tf.HeaderText = disciplines.Tables[0].Rows[i]["DISCP_DESC"].ToString();
                GridView1.Columns.Add(tf);
            }

            GridView1.DataSource = dt;
            GridView1.DataBind();

        }
    }
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if(e.Row.RowType == DataControlRowType.DataRow)
        {
            for(int i=1; i<GridView1.Columns.Count; i++)
            {
                CheckBox cb = new CheckBox();
                cb.Checked = false;
                cb.ID = (e.Row.RowIndex*100+i).ToString();
                e.Row.Cells[i].Controls.Add(cb);
            }
        }
    }
protected void submit_Click(object sender, EventArgs e)
    {
        StringBuilder resultString = new StringBuilder(); //string that will contain the cell numbers of checked checkboxes

        int num = GridView1.Columns.Count;
        for (int i = 1; i < num; i++)
        {
            foreach (GridViewRow row in GridView1.Rows)
            {
                if (row.RowType == DataControlRowType.DataRow)
                {
                    CheckBox cb = (CheckBox)row.FindControl((row.RowIndex*100+i).ToString());
                    if (cb.Checked)
                    {
                        resultString.Append(row.RowIndex.ToString());
                        resultString.Append("\t");
                        resultString.Append((i - 1).ToString());
                        resultString.Append("\n");
                    }
                }
            }
        }
        result.InnerText = resultString.ToString();
    }
  • 1
    When you create controls dynamically, you have to recreate them on *every* postback – Hans Kesting Dec 30 '19 at 11:27
  • ^^^^ you can really see this in action if you debug. Put a breakpoint on Page_Load and then another on Submit_Click, and see which one hits first. Try getting rid of the ````!(Page.IsPostBack)```` – JohnPete22 Dec 30 '19 at 15:57
  • Also, any time you are doing a ````FindControl```` I'd always do a null check afterwards. ````if (cb != null && cb.Checked)```` – JohnPete22 Dec 30 '19 at 18:33

0 Answers0