我似乎找不到我在网格视图中放置的用于选择行的复选框

I can't seem to find the checkbox I put in a gridview for selection of rows

提问人:ACME NOTARY 提问时间:11/26/2022 更新时间:11/26/2022 访问量:160

问:

我正在使用一个网格视图,我想选择一行,然后将该行放入数据表中以与转发器控件绑定。我无法使用我放在网格视图中的复选框控件查找所选行。我在互联网上搜索了一下,找到了一些关于递归查找控件的信息。我可以找到一个复选框控件,但是结果始终是“false”复选框。我的问题,当复选框被选中时,我是否需要做一些事情才能让网格视图知道发生了更改?该复选框未绑定到我的数据表中的任何数据,仅用于选择目的。

 <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"); 

上面的一行是一些代码,只是为了找到复选框。我正在试验,发现返回了一个复选框,但无论如何,它们都返回了 false,这导致我认为由于它们在开始时设置为未选中或 false,我需要做一些事情,但我不确定。我在互联网上找到的一切都表明它应该有效。让我知道你的想法。

下面是递归函数的代码。

 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;
}

我从一个类似的问题中找到了这个网站上的代码,并想看看它是否有效。

C# asp.net GridView FindControl

评论


答:

1赞 Albert D. Kallal 11/26/2022 #1

您不需要任何递归函数。

所以,用一个复选框说出这个 gv:

(它可以设置为表中的值,也可以不设置为 - 无关紧要)。

所以,这个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>

要加载的代码是这样的:

    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;
    }

我们现在看到/得到这个:

enter image description here

好的,对于单击/查看按钮,我们有以下代码:

    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");

    }

输出:

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

所以,上面是一个行点击示例。

但是,对于所有行,则:

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

输出:

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

当然,上面也可以显示数据库的 PK 值,而且很不错的是这样的值不必在 GV 中暴露客户端。

例如:

  int PKID = (int)GridView1.DataKeys[gRow.RowIndex]["ID];

评论

0赞 ACME NOTARY 11/26/2022
谢谢阿尔伯特!您的信息看起来很可靠,但我无法让它在我这边工作。只是为了清楚。Debug.Print 在我的环境中给了我一个错误。我正在使用 VS 2012。不确定我是否需要打开某些东西。当我单击该按钮时,gridview 消失,并且不会触发 cmdview 事件。我知道这些都是简单的问题。感谢您的耐心等待。
0赞 Albert D. Kallal 11/26/2022
Debug.Print 当然是测试代码 - 你不需要它。但是,您确实需要使用 System.Diagnostics 导入以使用 debug.print。由于 VS 在测试网站期间没有活动的控制台,因此我经常使用 debug.print。您还需要/想要/应该/好主意去 tools->options->debugging->[x] 将所有输出窗口文本重定向到即时窗口。因此,“调试”代码肯定不会影响发布的工作代码,除非您需要/想要使用 debug.print。但如前所述,只需使用 System.Diagnostics; 添加 Imports,然后执行调试代码的重定向选项。
0赞 ACME NOTARY 11/26/2022
谢谢阿尔伯特!我想看看我是否可以复制你的结果。所以谢谢你的信息。
0赞 ACME NOTARY 11/27/2022
我被困住了。我已将视图按钮放在我的表格中,单击后会进行回发。网格视图将消失,并且永远不会触发cmdView_Click事件。我做错了什么?
0赞 Albert D. Kallal 11/27/2022
哼,你必须编辑你的查询,并发布你所拥有的更多标记。当您将按钮放入 GV 时,您必须添加/连接 onclick 事件。因此,在标记中,您键入 onclick= ( 当您点击“=”时,inteli-sense 应该会弹出一个选项列表,其中一个是创建新事件。因此,让 VS 为您创建事件代码存根)。在这一点上,一切都应该可以正常工作。