0

I am working with a gridview which I want to select a row and then put the row in a datatable to bind with a repeater control. I am having trouble finding the selected rows using the checkbox control that I had put in the gridview. I have searched the internet and have found some information on finding controls recursively. I can find a checkbox control however the results are always a "false" checkedbox. My question, Do I need to do something when the checkbox is checked in order for the gridview to know that there was a change? The checkbox is not bound to any data in my datatable is is only used for selection purposes.

 <asp:GridView ID="GridView1" runat="server" HeaderStyle-BackColor="#191970" HeaderStyle-ForeColor="White" ShowFooter="false" RowStyle-Wrap="false"
            AlternatingRowStyle-BackColor="#80993c" AlternatingRowStyle-ForeColor="White" AutoGenerateColumns="false" GridLines="None" 
            EnableViewState="false" AllowSorting="true" ShowHeaderWhenEmpty="true" EmptyDataText="No Notaries found with the specified criteria." CssClass="GridView1" OnSorting="GridView1_Sorting1">
            <Columns>
                <asp:TemplateField>
                    <ItemTemplate>
                        <asp:CheckBox ID="notaryselect" runat="server" />
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:BoundField DataField="firstname" HeaderText="First Name" SortExpression="FirstName" />
                <asp:BoundField DataField="lastname" HeaderText="Last Name" SortExpression="LastName" />
                <asp:BoundField DataField="suffix" HeaderText="Suffix" />
                <asp:BoundField DataField="city" HeaderText="City" SortExpression="City" />
                <asp:BoundField DataField="state" HeaderText="State" SortExpression="State" />
                <asp:BoundField DataField="zipcode" HeaderText="Zip Code" SortExpression="Zipcode" />
                <asp:TemplateField>
                    <HeaderTemplate>Cell Phone</HeaderTemplate>
                    <ItemTemplate>
                        <asp:HyperLink ID="hyperCellPhone" runat="server" ForeColor="Gold"
                            NavigateUrl='<%# Eval("cellphone", "tel:{0}") %>'
                            Text='<%# Eval("cellphone") %>'></asp:HyperLink>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField>
                    <HeaderTemplate>Email</HeaderTemplate>
                    <ItemTemplate>
                        <asp:HyperLink ID="hyperEmail" runat="server"
                            NavigateUrl='<%# Eval("email", "mailto:{0}") %>'
                            Text='<%# Eval("email") %>'></asp:HyperLink>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:BoundField DataField="county" HeaderText="County" SortExpression="County" />
                <asp:BoundField DataField="lat" HeaderText="Latitude" />
                <asp:BoundField DataField="long" HeaderText="Longitude" />
            </Columns>
            <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" Width="50%" />
        </asp:GridView>

Control check = FindControlRecursive(GridView1.Rows[i], "notaryselect"); 

The above line is some code just to find the checkbox. I was experimenting and found that a checkbox is returned but no matter what they all come back false which is leading me to think that since they are set to unchecked or false at the start I need to do something but I am just not sure. Everything I find on the internet shows it should work. Let me know what your thoughts are.

Here is the code for the recursive function.

 public static Control FindControlRecursive(Control Root, string Id)
{
  if (Root.ID == Id)
    return Root;
  foreach (Control c in Root.Controls)
  {
    Control fc = FindControlRecursive(c, Id);
    if (fc != null)
      return fc;
  }
  return null;
}

I found that code on this site from a similar question and wanted to see if that worked.

1 Answers1

1

You don't need any recursive function.

So, say this gv with a check box:

(it can be set to a value in the table, or not - does not matter).

So, this gv:

            runat="server" CssClass="table" AutoGenerateColumns="false"
            width="42%" DataKeyNames="ID"  >
            <Columns>
                <asp:BoundField DataField="FirstName" HeaderText="FirstName"  />
                <asp:BoundField DataField="LastName" HeaderText="LastName"    />
                <asp:BoundField DataField="HotelName" HeaderText="Hotel Name"    />
                <asp:BoundField DataField="Description" HeaderText="Description" ItemStyle-Width="270" />
                <asp:TemplateField>
                    <ItemTemplate>
                        <asp:CheckBox ID="chkActive" runat="server"
                            Checked='<%# Eval("Active") %>' />
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="View">
                    <ItemTemplate>
                        <asp:Button ID="cmdView" runat="server" Text="view" 
                            CssClass="btn" OnClick="cmdView_Click" />
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>

Code to load is this:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            LoadData();
    }

    void LoadData()
    {
        string strSQL = "SELECT * FROM tblHotelsA ORDER BY HotelName";
        DataTable rstData = MyRst(strSQL);
        GridView1.DataSource = rstData;
        GridView1.DataBind();
    }

    public DataTable MyRst(string strSQL)
    {
        DataTable rstData = new DataTable();
        using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
        {
            using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
            {
                cmdSQL.Connection.Open();
                rstData.Load(cmdSQL.ExecuteReader());
            }
        }
        return rstData;
    }

And we now see/get this:

enter image description here

Ok, so for the click/view button, we have this code:

    protected void cmdView_Click(object sender, EventArgs e)
    {
        Button btnView = (Button)sender;
        GridViewRow gRow = (GridViewRow)btnView.NamingContainer;

        Debug.Print("Row index click = " + gRow.RowIndex);
        int PK = (int)GridView1.DataKeys[gRow.RowIndex]["ID"];
        Debug.Print("Database PK id = " + PK);

        CheckBox ckActive = (CheckBox)gRow.FindControl("chkActive");

        if (ckActive.Checked)
            Debug.Print("check box is true");
        else
            Debug.Print("Check box is false");

    }

output:

Row index click = 2
Database PK id = 7
Check box is false

So, above is a row click sample.

But, for all rows, then this:

        foreach (GridViewRow gRow in GridView1.Rows)
        {
            CheckBox ckBox = (CheckBox)gRow.FindControl("chkActive");
            Debug.Print($"Row index = {gRow.RowIndex} Checkbox value = {ckBox.Checked.ToString()}");
        }

output:

Row index = 0 Checkbox value = True
Row index = 1 Checkbox value = False
Row index = 2 Checkbox value = False
Row index = 3 Checkbox value = True
Row index = 4 Checkbox value = False
Row index = 5 Checkbox value = True
Row index = 6 Checkbox value = True
Row index = 7 Checkbox value = True

And of course, above could also display the database PK value, and quite nice is such values don't have to be exposed client side in the GV.

eg:

  int PKID = (int)GridView1.DataKeys[gRow.RowIndex]["ID];
Albert D. Kallal
  • 42,205
  • 3
  • 34
  • 51
  • Thank you Albert! Your info looks solid but I am not able to get it to work on my end. Just to be clear. The Debug.Print gives me an error in my environment. I am using VS 2012. Not sure if I need to turn something on. When I click on the button the gridview disappears and the cmdview event is not fired. I know these are simple questions. Thanks for your patience. – ACME NOTARY Nov 26 '22 at 01:45
  • Debug.Print is of course testing code - you don't need it. But you do need to import using System.Diagnostics for using debug.print. Since VS does not have a active console during testing a web site, then I often use debug.print. You also need/want/should/good idea to go tools->options->debugging->[x] Redirect all output window text to the immediate window. So, "debugging" code certainly not going to effect the posted working code unless you need/want to use debug.print. But as noted, just add Imports using System.Diagnostics;, and do the re-direct in options for debug code. – Albert D. Kallal Nov 26 '22 at 02:56
  • Thanks Albert! I wanted to see if I could duplicate your results. So thankyou for the information. – ACME NOTARY Nov 26 '22 at 04:42
  • I am stuck. I have placed the view button in my table and when clicked a postback is made. The gridview disappears and the cmdView_Click event is never fired. What am I doing wrong? – ACME NOTARY Nov 26 '22 at 16:53
  • Hum, you have to edit your quesiton, and post more markup of what you have. When you drop in the button to the GV, you then have to add/wire up the onclick event. So, in markup you type in onclick= ( when you hit "=", then inteli-sense should pop up a list of options, one being to create new event. So, let VS create the event code stub for you). At this point everything should work. – Albert D. Kallal Nov 26 '22 at 17:04
  • You need to leave view-state on. (else you hvae to re-load the gv each time on each post-back. So, some for sure prefer to turn viewsate off, but for now, delete your gv tag that disables viewstate. – Albert D. Kallal Nov 26 '22 at 17:06
  • Sorry Albert I feel dumb. I did have viewstate set to false so that fixed the problem when I made it true, but I then could not get it working. I copied your checkbox line but did not name my checkbox with your name so of course, the computer could not find the control. I fixed that now. Thank you for your patience. – ACME NOTARY Nov 26 '22 at 21:26
  • All good then - do mark this as an answer ! – Albert D. Kallal Nov 27 '22 at 01:03