GridView problems ... Foreach loop help needed

Making the way into GridView programming and losing my mind...

First, my 2 databases, with a composite key....  (Filtered here for simple look)

TABLE [dbo].[Table1](
	[Tab1RequestDate] [datetime] NOT NULL,
	[Tab1RequestType] [char](20) NOT NULL,
	[Tab1EmpID] [char](6) NOT NULL,
	[Tab1EmpLastName] [varchar](30) NULL,
	[Tab1EmpFirstName] [varchar](30) NULL,
	[Tab1HireMgrID] [char](6) NULL,
	[Tab1SentFeedback] [bit] NULL,
	[Tab1CompletionDate] [date] NULL,
	[Tab1RequestDate] ASC,
	[Tab1EmpID] ASC

TABLE [dbo].[Table2](
	[Tab2RequestDate] [datetime] NOT NULL,
	[Tab2EmpID] [char](6) NOT NULL,
	[Tab2EmpLastName] [varchar](30) NULL,
	[Tab2EmpFirstName] [varchar](30) NULL,
	[Tab2MgrID] [char](6) NULL,
	[Tab2SentFeedback] [bit] NULL,
	[Tab2CompletionDate] [date] NULL,
	[Tab2RequestDate] ASC,
	[Tab2EmpID] ASC

Open in new window

My Gridview definition....   DATAKEY Is what is not friendly to me.... (More in CS logic)

aspx file logic
         <asp:GridView ID="FeedbackGridView" runat="server"
                DataKeyNames="?????????????????????????????? HELP!!!!!!"
                SelectedRowStyle-BackColor="Wheat" BackColor="#DEBA84" BorderColor="#DEBA84" BorderStyle="None" BorderWidth="1px" 
                            <asp:Label ID="Label1" runat="server"
                                Text="Select All" />
                            <asp:CheckBox ID="chkHeader" runat="server" />
                            <asp:CheckBox ID="chkRow" runat="server" />
                    <asp:BoundField DataField="OnOffFlag" HeaderText="Type" ReadOnly="True" />
                    <asp:BoundField DataField="RequestDateYYYYMMDD" HeaderText="Request Date" DataFormatString="{0:d}" ItemStyle-HorizontalAlign="Center" ReadOnly="True" />
                    <asp:BoundField DataField="Tab1HireMgrID" HeaderText="Manager ID" ItemStyle-HorizontalAlign="Center" ReadOnly="True" />
                    <asp:BoundField DataField="Tab1EmpID" HeaderText="New Hire ID" ItemStyle-HorizontalAlign="Center" ReadOnly="True" />
                    <asp:BoundField DataField="EmpName" HeaderText="New Hire Name" ReadOnly="True" />
                    <asp:BoundField DataField="Tab1RequestType" HeaderText="New Hire Type" ReadOnly="True" ItemStyle-HorizontalAlign="Center" />
                    <asp:BoundField DataField="Tab1CompletionDate" HeaderText="Date Completed" DataFormatString="{0:d}" ItemStyle-HorizontalAlign="Center" ReadOnly="True" />
                <FooterStyle BackColor="#F7DFB5" ForeColor="#8C4510" />

                <HeaderStyle HorizontalAlign="Center" Wrap="True" BackColor="#A55129" Font-Bold="True" ForeColor="White"></HeaderStyle>

                <PagerStyle ForeColor="#8C4510" HorizontalAlign="Center" />
                <RowStyle BackColor="#FFF7E7" ForeColor="#8C4510" />

                <SelectedRowStyle BackColor="#738A9C" Font-Bold="True" ForeColor="White"></SelectedRowStyle>

            <asp:SqlDataSource ID="FeedbackDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:digitallifeConnectionString %>" SelectCommand="SELECT 
'Onboard' as OnOffFlag
,CONVERT (DATE, Tab1RequestDate) as RequestDateYYYYMMDD
,Tab1FirstName + ' ' + Tab1LastName as EmpName
FROM dbo.Table1 as tbl_on
WHERE (tbl_on.CompletionDate Is Null) AND (tbl_on.SentFeedback Is Null)


'Offboard' as OnOffFlag
,CONVERT (DATE, RequestDate) as RequestDateYYYYMMDD
,' ' as Tab2RequestType
,Tab2EmpFirstName + ' ' + Tab2EmpLastName as EmpName
FROM dbo.Table2 as tbl_off
WHERE (tbl_off.CompletionDate Is Null) AND (tbl_Off.SentFeedback Is Null)

Open in new window

Now, the .cs code-behind  executed when btnSubmit (Send Email Requests) is hit.  

        protected void btnSubmit_OnClick(object sender, EventArgs e)
            if (Page.IsValid)
                CheckBox chk;

                foreach (GridViewRow rowItem in FeedbackGridView.Rows)
                    // FindControl function gets the control placed inside the GridView control from the specified cell
                    // FindControl fucntion accepts string id of the control that you want to access
                    // type casting of control allows to access the properties of that particular control
                    // here checkbox control type cast is used to access its properties
                    chk = (CheckBox)(rowItem.Cells[0].FindControl("chkRow"));
                    // chk.checked will access the checkbox state on button click event
                    if (chk.Checked)
                        Response.Write(FeedbackGridView.DataKeys[rowItem.RowIndex]["categoryID"].ToString() + "<br />");	
//		Will SEND MAIL here fr each checked box...

Open in new window

Build and set up....  I get an "Object reference not set to an instance of an object."  Know what it means...  but where?

Basic trouble... loop the table, send an email with each checked entry....  then update the Table1 or table2 Feedback sent.
Bob BenderAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Kyle AbrahamsSenior .Net DeveloperCommented:
You have to check if the row Is a header row versus a data row.  The checkbox isn't displayed on the header row which is your problem.  

Chk is null on the header row at
 chk = (CheckBox)(rowItem.Cells[0].FindControl("chkRow"));
For the DataKeyNames property, you have an example at Use a comma-separated list:

Open in new window

Johny BravoCommented:
>>  chk = (CheckBox)(rowItem.Cells[0].FindControl("chkRow"));
Should be
CheckBox chk = (CheckBox)rowItem.FindControl("chkRow");
Amazon Web Services

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

Bob BenderAuthor Commented:
Okay, to understand between the comments of Kyle and Johny...

Kyle...  Ya said the Checkbox on the HeaderRow is NOT displayed.   I thought the header is the line with the SELECT ALL and checkbox....   (True, I want to check the data rows, (ChkRow)... but I thought that would not reference the Header) . Does rowItem.Cells[0] refer to the header entry to "select all"?   After all that is a ROW in the total look of the GV.  Help me understand.  

Johny....  And to expand on my comment to Kyle,  changing the rowitems.cells[0] in my line to rowItem makes it look ONLY at entries that have the ChkRow  'name'?
Bob BenderAuthor Commented:
Louisfr....   So, the datakeys really refer to whatever makes up the primary key of the database????  

And if they are not 'defined',  I can check certain events to get the datakey from the 'e' object.?  At least that is what I think I understand?
Bob BenderAuthor Commented:
I Added a trace option to the Page Directives.   When I click the "Submit" button,

The Trace gives me... Begin ProcessPostData Second Try 0.00110729427101207 0.000022 End ProcessPostData Second Try 0.00112649313136772 0.000019 Begin Raise ChangedEvents 0.00114761187775894 0.000021 End Raise ChangedEvents 0.00117353033923906 0.000026 Begin Raise PostBackEvent 0.00119368914261249 0.000020 
Unhandled Execution Error 
Object reference not set to an instance of an object.
  at Portal.Admin.FeedBack_Requester.btnSubmit_OnClick(Object sender, EventArgs e)
  at System.Web.UI.WebControls.Button.OnClick(EventArgs e)
  at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
  at System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
  at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
  at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
  at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) 

Open in new window

Never used this much....   Could it possible be related to a jquery routine that handles the checkmarks?

Trying to find ideas....
Johny BravoCommented:
Hi Bob Bender,

You are using TemplateFields so you can get the Controls in the ItemTemplate directly, no need to do Cells[0]

Have you tried?
Bob BenderAuthor Commented:
I had changed the statement based on the comments here, but still have the Object Error....

to which I posted the trace that I added to directive....
Kyle AbrahamsSenior .Net DeveloperCommented:
Try the following:
  if (chk != null && chk.Checked)
                      bool isNull = false;

//just debugging
                          if (FeedbackGridView.DataKeys[rowItem.RowIndex] == null)
                             //set breakpoint here.  
                                  isNull = true;
                          else if (FeedbackGridView.DataKeys[rowItem.RowIndex]["categoryID"] == null)
                            //also set here.
                                isNull = true;

                        Response.Write(FeedbackGridView.DataKeys[rowItem.RowIndex]["categoryID"].ToString() + "<br />");      
//            Will SEND MAIL here fr each checked box...
  else if (chk == null)
   //debug, set a break point here, should never be reached.
              chk = chk;
Johny BravoCommented:
foreach (GridViewRow GR in GridView1.Rows)
     if (GR.RowType == DataControlRowType.DataRow)
CheckBox chk = (CheckBox)(GR.FindControl("chkRow"));

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Bob BenderAuthor Commented:
johny_bravo1... This line  [ if (GR.RowType == DataControlRowType.DataRow) ] is making us look at DataItems and not HeaderRows?  As outlined in the ItemTemplate?
Bob BenderAuthor Commented:
Kyle....   Makes sense, and lead me to using some more Response.Write's to find the process of what is happening.

All along, the problem was with the DataKeys in a way,  Not properly defined as CategoryID,  Missed that from the sample I used for starters.

You and Johny have been both instrumental in moving me forward.
Bob BenderAuthor Commented:
working together to get a solution...  Thanx to both of ya!!!!
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.