如何将 GridView 中的行数作为参数传递给 OnRowCommand 调用

How do I pass the number of rows in GridView as an argument to OnRowCommand call

我正在尝试仅当 GridView 中有超过 1 行时才在 GridView 上动态显示按钮和复选框。 (视图是基于搜索用户的结果,因此行数是基于搜索结果的动态)

按钮和复选框的用途是允许我合并 2 个或更多用户帐户。如果 GridView 中只有 1 行(令人困惑),则显示此按钮毫无意义,因此我使用函数设置 "Visible" 参数。但是,在此函数中使用 GridViewID.Rows.Count 不起作用。 (我认为它实际上是调用函数时显示的最大行数)。即:从 Gridview 的第二行调用给我 Row.Count=2。所以我试图传递一个隐藏的控件,但它不起作用。

这是我的代码:

<asp:GridView ID="GridView1" runat="server" OnRowCommand="GridView1_RowCommand">
<Columns>
        <asp:TemplateField ShowHeader="false">
            <ItemTemplate>
                <asp:HiddenField ID="HiddenUserID" runat="server" Visible="false" Value= '<%#Eval("UserID") %>' ></asp:HiddenField> 
                    <asp:HiddenField ID="NumberRowsGridView" runat="server" Visible="false" Value='<%#Bind("NumberRowsGridView") %>'></asp:HiddenField>
            </ItemTemplate>
            </asp:TemplateField>
            <asp:BoundField DataField="UserName" HeaderText="User Name"/>
            <asp:BoundField DataField="Email" HeaderText="Email Address"/>
 <asp:TemplateField ShowHeader="false">
        <ItemTemplate>
                <asp:CheckBox ID="CheckBox1" runat="server" Visible='<%# ShowMergeUserButton((String)Eval("UserName"),(String)Eval("Email"),(String)Eval("NumberRowsGridView")) %>' />
            </ItemTemplate>
     </asp:TemplateField>

     <asp:TemplateField ShowHeader="True" HeaderText="Merging Actions">
        <ItemTemplate>
                <asp:Button ID="Button3" runat="server" CausesValidation="false" CommandName="MergeIntoUser"
                    Text="Merge Into This Account" CommandArgument='<%# Container.DataItemIndex + "," + Eval("UserID")%>' Visible='<%# ShowMergeUserButton((String)Eval("UserName"),(String)Eval("Email"),(String)Eval("NumberRowsGridView")) %>'/>
            </ItemTemplate>
 </asp:TemplateField>
     </Columns>

函数背后的代码:

protected Boolean ShowMergeUserButton(String Username, String Email, String NumRows)
{
return (Username == Email && Convert.ToInt32(NumRows) > 1);
}

我创建了一个隐藏字段并尝试将其插入到 GridView 中,但我的代码出现运行时错误:(注意,我是 ASP 的新手:)

protected System.Web.UI.WebControls.HiddenField NumberRowsGridView;

-- 在填充 GridView 的函数中 -- dt 为数据源

GridView1.DataSource = dt; 
GridView1.DataBind();
NumberRowsGridView.Value = dt.Count<items>().ToString();

我得到的错误是: System.Web.HttpException: DataBinding: 'MyASPPageName+dt' 不包含名称为 'NumberRowsGridView' 的 属性。

所以我基本上完全错了。

由于 OnRowCommand 是一个事件,您可以从事件处理程序中获取该信息。在您的代码隐藏中找到 GridView1_RowCommand 事件处理程序并将对象发送者转换为 GridView,如下所示...

void GridView1_RowCommand(Object sender, GridViewCommandEventArgs e)
{
    GridView gridView = (GridView)sender;
    int numOfRows = gridView.Rows.Count;
    // Now you can  do something with numOfRows!
}

至于您想做的其他事情,您可能想创建一个更具体到那些其他任务的新问题。但是不需要将行数传递给 GridView 的事件处理程序,因为发送者对象(触发事件的 GridView)将具有所有这些属性。希望这有帮助。

我不确定你想要完成什么,但这应该可以解决你的问题:

在您的代码中添加这样的 属性,ViewState 将在页面的整个生命周期中保持您的价值。

public string NumberRowsGridView
{
    get { return ViewState["NumberRowsGridView"] == null ? null : ViewState["NumberRowsGridView"].ToString(); }
    set { ViewState["NumberRowsGridView"] = value; }
}

现在像这样编辑这部分代码

NumberRowsGridView = dt.Count<items>().ToString();
GridView1.DataSource = dt; 
GridView1.DataBind();

和这样的按钮标记

<asp:Button ID="Button3" runat="server" ... Visible='<%# ShowMergeUserButton((String)Eval("UserName"),(String)Eval("Email"), NumberRowsGridView) %>'/>

它应该可以正常工作

这不会回答您关于如何在标记中执行此操作的问题,但是当事情变得如此复杂时,我喜欢采用更简单的方法。您可以做的是 hide/show 绑定整个 GridView 后的按钮。

DataBound 事件添加到您的 GridView。

<asp:GridView ID="GridView1" runat="server"
    OnRowCommand="GridView1_RowCommand"
    OnDataBound="GridView1_DataBound">

那么在这个事件中,你所有的行都被绑定了。因此,如果您有不止一行,请显示按钮。如果没有,请隐藏按钮。这应该会给你一个想法。

protected void GridView1_DataBound(object sender, EventArgs e)
{
    if (GridView1.Rows.Count > 1)
    {
        foreach (GridViewRow row in GridView1.Rows)
        {
            Button Button3 = (Button)row.FindControl("Button3");
            Button3.Visible = true;
        }
    }
}

如果您必须在标记中这样做,Enrique Zavaleta 的回答应该可以帮助您。