0

I am not able to pre-populate CheckBoxList3 in my app. I have successfully retrieved string data from database and passed to array but routine fails with:

NullReferenceException:Object not set to instance of an object error at line:
ListItem currentCheckBox = cb3.Items.FindByValue(items[i].ToString());

readMyString() method uses SqlDataReader to read and split a string column from SQL table then pass the values for example: "A, B, C" to string array to identify which of 6 checkboxes should be selected. Code reference: [http://mikesdotnetting.com/Article/53/Saving-a-user's-CheckBoxList-selection-and-re-populating-the-CheckBoxList-from-saved-data]

HTML CODE:

<asp:GridView ID="GridView1" runat="server" 
              AutoGenerateColumns="False" CellPadding="4" DataKeyNames="MyID"   
              DataSourceID="sdsmyTable1" ForeColor="#333333" GridLines="None" 
              onrowdeleted="GridView1_RowDeleted" 
              onrowdeleting="GridView1_RowDeleting" 
              onrowupdated="GridView1_RowUpdated"  
              onrowupdating="GridView1_RowUpdating" 
              onselectedindexchanged="GridView1_SelectedIndexChanged" 
              onrowediting="GridView1_RowEditing" 
              onrowcancelingedit="GridView1_RowCancelingEdit" 
              onrowdatabound="GridView1_RowDataBound">
    <RowStyle BackColor="#EFF3FB" />

    <Columns>
        <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />

        <asp:BoundField DataField="myID" HeaderText="myID" ReadOnly="True" 
                        SortExpression="myID" />

        <asp:BoundField DataField="Date1" HeaderText="Date driver lic issued" 
                        SortExpression="Date1" />

        <asp:TemplateField HeaderText="chooseOne" SortExpression="chooseOne">
            <ItemTemplate>
                <asp:Label ID="Label1" runat="server" Text='<%# Bind("chooseOne") %>'></asp:Label>
            </ItemTemplate>
            <EditItemTemplate>                
                <asp:RadioButtonList ID="RadioButtonList2" runat="server" SelectedValue='<%# Bind("chooseOne") %>' Font-Size="Small" 
                                     RepeatDirection="Horizontal">
                    <asp:ListItem Value="1">1</asp:ListItem>
                    <asp:ListItem Value="2">2</asp:ListItem>
                    <asp:ListItem Value="3">3</asp:ListItem>
                </asp:RadioButtonList>
            </EditItemTemplate>

        </asp:TemplateField>
        <asp:TemplateField HeaderText="MyCommaSeparatedString" SortExpression="MyCommaSeparatedString">
            <ItemTemplate>
                <asp:Label ID="Label2" runat="server" Text='<%# Bind("MyCommaSeparatedString") %>'></asp:Label>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("MyCommaSeparatedString") %>'></asp:TextBox>
                <asp:CheckBoxList ID="CheckBoxList3" runat="server" Font-Size="Small"  
                                  RepeatDirection="Horizontal">                              
                    <asp:ListItem Value="A">A</asp:ListItem>
                    <asp:ListItem Value="B">B</asp:ListItem>
                    <asp:ListItem Value="C">C</asp:ListItem>                   
                    <asp:ListItem Value="D">D</asp:ListItem>
                    <asp:ListItem Value="E">E</asp:ListItem>
                    <asp:ListItem Value="F">F</asp:ListItem>           
                </asp:CheckBoxList>
            </EditItemTemplate>

C# Code:

    protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            //// establish a datarow to dig into its minutia
            DataRowView drv = e.Row.DataItem as DataRowView;

            // if 1: RowType of gridview control is a datarow 
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                //if 2: is datarow in edit mode
                if ((e.Row.RowState & DataControlRowState.Edit) > 0)
                {
                  RadioButtonList rb2 = (RadioButtonList)e.Row.FindControl("RadioButtonList2");
                  CheckBoxList cb3 = (CheckBoxList)e.Row.FindControl("CheckBoxList3");
//CheckBoxList cb3 = (CheckBoxList)GridView1.Rows[GridView1.EditIndex].FindControl("CheckBoxList3");
                  CheckBoxList cb4 = (CheckBoxList)e.Row.FindControl("CheckBoxList4");

                    // Create an instance of SqlConn class            
                    SqlConnClass getMyStr= new SqlConnClass();

                    //Return datareader to read Endorsements column from database
                    SqlDataReader rdr = getMyStr.selectMyString(GetMyID());

                    try
                    {
                        // column
                        if (rb2 != null)
                        {
                            rb2.SelectedValue = drv[2].ToString();
                        }

                        // column                    
                        //CheckBoxList cb3 = (CheckBoxList)e.Row.FindControl("CheckBoxList3");
                        if (cb3 != null)//if (cb3 contains 6 checkboxes (I, N, H, X, T, K)
                        {
                            //bind checkbox manually
                            cb3.DataSource = sdsDatasource;
                            cb3.DataTextField = "MyCommaSeparatedString ";
                            cb3.DataValueField = "MyCommaSeparatedString ";
                            cb3.DataBind();

                            // if row exists
                            if (rdr.HasRows)//(dt.Rows.Count > 0 && dt != null)
                            {
                                //start reading
                                rdr.Read();

                //extract comma separated string from datareader into one-dimensional array    
                                string[] items = rdr.GetString(0).Split(',');

               //returns the upper bound for the indexes of the first dimension of the Array
                                for (int i = 0; i <= items.GetUpperBound(0); i++)
                                {
              // currentCheckBox IS WHERE NULL OCCURS: 
              ListItem currentCheckBox = cb3.Items.FindByValue(items[i].ToString());

                                    if (currentCheckBox != null)
                                    {
                                        currentCheckBox.Selected = true;
                                    }
                                    //cb3.SelectedValue = drv[3].ToString();
                                    //}
                                }// end of for

                                //close SqlDataReader
                                rdr.Close();
                            }

                        // column
                        //CheckBoxList cb4 = (CheckBoxList)e.Row.FindControl("CheckBoxList4");
                        if (cb4 != null)
                        {
                            cb4.SelectedValue = drv[4].ToString();
                        }

                        }// end of if
                    }// end of try

                    catch (IndexOutOfRangeException ex2)
                    {
    System.Diagnostics.Debug.WriteLine(ex2.Message + "; " + ex2.Source + "; " + ex2.TargetSite);
                    }//end of catch                
                }// end of if (rowstate)
            } // end of if (rowtype)
        }// end of method

What I have tried: calling readMyString() method from GridView1_RowDataBound event and/or from GridView1_RowEditing event.

Since CheckBoxList3 is empty to begin with and seems to not want to be null, I added the line cb3.Items[i].Value = items[i]; but the error just moves to the new line instead. I must be missing something.

Can anyone see where I've errored? I must be putting the code in the wrong methods...?

Doreen
  • 714
  • 2
  • 14
  • 36

1 Answers1

0

You are trying to find the control in the GridView. The controls are inside the GridView Rows. So you need to do something like this:

CheckBoxList cb3 = (CheckBoxList) GridView1.Rows[GridView1.EditIndex].FindControl("CheckBoxList3");

Trim the items[i] like below:

ListItem currentCheckBox = cb3.Items.FindByValue(items[i].Trim());
gbs
  • 7,196
  • 5
  • 43
  • 69
  • I used your example and now getting error on the new line of code: 'ArgumentOutOfRangeException was unhandled by user code: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index.' I tried replacing part of code '.Rows[GridView1.EditIndex]' with '.Rows[0]'. No change. There is only one row to edit in this particular gridview and there will always only be one row. – Doreen Feb 05 '14 at 23:37
  • as a follow up I moved my code to _RowDataBound event when I received the ArgumentOutOfRangeException on new line of code. I then moved code to _RowEditing event and previous error popped up again Object reference...on the old line of code. – Doreen Feb 06 '14 at 00:02
  • Can you set a breakpoint and see if it is cb3 that is null or FindByValue returning null? – gbs Feb 06 '14 at 00:17
  • When you moved your code to RowDataBound did you put it in a if block to make sure GridView RowState is in edit mode? Check this: http://stackoverflow.com/questions/14584175/how-to-find-control-in-edit-item-template – gbs Feb 06 '14 at 00:34
  • I added the code to check for edit mode and now cb3 is not null BUT currentCheckBox is null AFTER I pass cb3 to it in this line: `ListItem currentCheckBox = cb3.Items.FindByValue(items[i].ToString());` No error is thrown but since it's null, checkboxes are not selected in fact they all go away except one, and only the selected Text labels show up. I am not sure how to set up the re-databinding in your referenced article since I'm getting the concatenated string value using datareader from GridView1's datasource. Should I create a separate DataSet to work with this one column? – Doreen Feb 06 '14 at 17:25
  • Why do you have this line: cb3.Items[i].Value = items[i]; What does it do? And is your CBL dynamic or has static values? – gbs Feb 06 '14 at 17:40
  • I removed `cb3.Items[i].Value = items[i];`(was grasping at straws at the time). CBL is static, it should always display all checkboxes and only the values after splitting the string should populate corresponding CBL check box. – Doreen Feb 06 '14 at 18:15
  • So did removing that line change anything? I don't see a reason why the CBLitems will be removed if it is a static one. Can you update the code in your question to what you have currently. – gbs Feb 06 '14 at 18:25
  • OK, I updated my code. (Thank you for assisting me, I hope we figure this out). – Doreen Feb 06 '14 at 19:14
  • If you hover over the cb3.Items on that findbyvalue line do you see all the values? Also make sure the values you are trying to find is case-matched and no spaces around. Also why are you rebinding the cb3 if it's having the values in it? – gbs Feb 06 '14 at 19:31
  • `cb3.Items:` I expanded Non-Public members, then expanded listItems, all 6 values were present, but none were selected (because that is the next step). FYI `items[i]` shows the 3 extracted values correctly. I did rebinding because was following reference in link you offered. Hmmm, no spaces around. Maybe my split method needs to trim also? By all appearances in debugger and checkboxlist3, there seems to be no spaces.... – Doreen Feb 06 '14 at 19:51
  • I can't think of anything else since it's the FindByValue not returning the item How about trying it with some hardcoded value. e.g. ListItem currentCheckBox = cb3.Items.FindByValue("A"); where "A" is the value of one of the list item. See if that is returning the listitem – gbs Feb 06 '14 at 20:43
  • I changed this line of code to: `string[] items = rdr.GetString(0).Split(new char[]{','},StringSplitOptions.RemoveEmptyEntries);` now currentCheckBox recognizes the 1st item value (of 3 that are true). Indexes 1 and 2 pass as null when in fact they are not. Only one checkbox is checked, albeit the correct one though. – Doreen Feb 06 '14 at 21:46
  • Can you try this: items[i].Trim()? It really doesn't make sense if it works for one and not for others. Make sure the for loop is executed 3 times. – gbs Feb 06 '14 at 21:55
  • Bingo! Thank you for stepping me through debugging process. I am very grateful. I have a lot of work left to do but this was my biggest hurdle thus far. HOW DO I mark your comment to use `items[i].Trim()` as answer? – Doreen Feb 06 '14 at 22:24
  • Glad it's working. You cannot mark the comment as an answer. I edited my answer though to include that comment. – gbs Feb 06 '14 at 22:45