TemplateField中的Gridview按钮仅在第二次单击时触发

时间:2013-03-04 11:09:46

标签: c# asp.net gridview templatefield

我在询问之前已经做了一些搜索,虽然this post已经接近,但它对我的情况不起作用。

我发现我的模板字段中的“删除”按钮似乎触发,但点击事件不会触发。然而,第二次单击按钮时,它按预期工作。

因此,打破代码,我使用`SqlDataSource将数据绑定到GridView

我的页面加载事件开始如下:

if (!Page.IsPostBack)  
{  
    externalUserDataSource.ConnectionString = "some connection string";  
}

我的数据来源如下:

<asp:SqlDataSource ID="externalUserDataSource" runat="server" 
    ConflictDetection="CompareAllValues" SelectCommand="uspGetExternalUsersByTeam"
SelectCommandType="StoredProcedure" ProviderName="System.Data.SqlClient">
<SelectParameters>
    <asp:SessionParameter Name="TeamID" SessionField="TeamID" Type="Int32" />
</SelectParameters>
</asp:SqlDataSource>

这是我的GridView标记:

<asp:GridView ID="gridView" runat="server" AutoGenerateColumns="False" 
    BackColor="White" BorderColor="#3366CC" BorderStyle="None" BorderWidth="1px" 
    CellPadding="4" DataKeyNames="LoginID" DataSourceID="externalUserDataSource" 
    EnableModelValidation="True" OnRowDataBound="GridViewRowDataBound" TabIndex="3">
        <HeaderStyle BackColor="#003399" Font-Bold="True" ForeColor="White" />
        <FooterStyle BackColor="#99CCCC" ForeColor="#003399" />
        <PagerStyle BackColor="#99CCCC" ForeColor="#003399" HorizontalAlign="Left" />
        <RowStyle BackColor="LightGoldenrodYellow" />
        <SelectedRowStyle BackColor="#009999" Font-Bold="True" ForeColor="#CCFF99" />
        <Columns>
            <asp:BoundField DataField="RowID" HeaderText="Row ID" ReadOnly="True" 
                SortExpression="RowID" Visible="False" />
            <asp:BoundField DataField="LoginID" HeaderText="Login ID" ReadOnly="True" 
                SortExpression="LoginID" Visible="False" />
            <asp:BoundField DataField="EmailAddress" HeaderText="Email Address" 
                ItemStyle-VerticalAlign="Bottom" ReadOnly="True" SortExpression="AssociateName"/>
            <asp:BoundField DataField="TeamID" HeaderText="Team ID" ReadOnly="True" 
                SortExpression="TeamID" Visible="False" />
            <asp:CheckBoxField DataField="HasFIAccess" 
                 HeaderText="Has Access to&lt;br /&gt;Funding&lt;br/&gt;Illustrator" 
                 ItemStyle-HorizontalAlign="Center" ItemStyle-VerticalAlign="Bottom" 
                 ReadOnly="True"/>
            <asp:CheckBoxField DataField="HasALTAccess" 
                 HeaderText="Has Access to&lt;br /&gt;Asset Liability&lt;br/&gt;Tracker" 
                 ItemStyle-HorizontalAlign="Center" ItemStyle-VerticalAlign="Bottom"
                 ReadOnly="True"/>
            <asp:CheckBoxField DataField="HasFIAAccess" 
                 HeaderText="Has Access to&lt;br /&gt;Funding&lt;br/&gt;Illustrator App" 
                 ItemStyle-HorizontalAlign="Center" ItemStyle-VerticalAlign="Bottom"
                 ReadOnly="True"/>                    
            <asp:TemplateField>
            <ItemTemplate>
                <asp:Button runat="server" CssClass="additionsRow" ID="btnDeleteExternalUser" OnClick="DeleteExtUserButtonClick" 
                    CausesValidation="False" Text="Delete" 
                    CommandArgument='<%#Eval("TeamID") + "," + Eval("LoginID") + "," + Eval("EmailAddress") + "," + Eval("HasALTAccess")%>'/>                            
            </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

因此,您可以看到我在事件中使用的按钮中传递了一些信息,以确保删除正确的数据(这就是我无法使用ButtonField的原因,如链接中所示上文)。

拼图的最后一部分是GridView的数据绑定事件:

        protected void GridViewRowDataBound(object sender, 
                                        GridViewRowEventArgs e)
    {
        // if rowtype is not data row...
        if (e.Row.RowType != DataControlRowType.DataRow)
        {
            // exit with no further processing...
            return;
        }

        // get the ID for the selected record...
        var selectedId = DataBinder.Eval(e.Row.DataItem, "RowID").ToString();

        // create unique row ID...
        e.Row.ID = string.Format("ExtUserRow{0}", selectedId);

        // find the button delete for the selected row...
        var deleteButton = (Button)e.Row.FindControl("btnDeleteExtUser");

        // get the email address for the selected record...
        var selectedUser = DataBinder.Eval(e.Row.DataItem, "EmailAddress").ToString();

        // define the message text...
        var messageText = string.Format("OK to delete {0}?",
                                        selectedUser.Replace("'", "\\'")); 

        // add attribute to row delete action...
        this.AddConfirmMessage(deleteButton, messageText);
    }  

其中AddConfirmMessage只是为控件分配一个onclick属性,以确保用户必须确认删除。

现在,在每种情况下,消息都会弹出'确定删除abc@xyz.com?',但如前所述,分配给“删除”按钮的事件直到第二次单击按钮。

奇怪的是,我从另一个页面中获取了这些代码并进行了相应的修改,尽管它没有这个问题:

        protected void DeleteExtUserButtonClick(object sender, 
                                            EventArgs e)
    {
        // get the buton which was clicked...
        var button = (Button)sender;

        // break the delimited array up...
        string[] argumentArray = button.CommandArgument.Split(',');

        // store the items from the array...
        string teamId = argumentArray[0];
        string loginId = argumentArray[1];
        string emailAddress = argumentArray[2];
        string hasAltAccess = argumentArray[3];

        using (var conn = new SqlConnection(Utils.GetConnectionString()))
        {
            // create database command...
            using (var cmd = new SqlCommand())
            {
                // set the command type...
                cmd.CommandType = CommandType.StoredProcedure;

                // set the name of the stored procedure to call...
                cmd.CommandText = "uspDeleteExternalUser";

                // create and add parameter to the collection...
                cmd.Parameters.Add(new SqlParameter("@TeamId", SqlDbType.Int));

                // assign the search value to the parameter...
                cmd.Parameters["@TeamId"].Value = teamId;

                // create and add parameter to the collection...
                cmd.Parameters.Add(new SqlParameter("@LoginId", SqlDbType.VarChar, 50));

                // assign the search value to the parameter...
                cmd.Parameters["@LoginId"].Value = loginId;

                // set the command connection...
                cmd.Connection = conn;

                // open the connection...
                conn.Open();

                // perform deletion of user...
                cmd.ExecuteNonQuery();
            }
        }

        // bind control to refresh content...
        ExtUsersGrid.DataBind();
    }

我错过了一些明显的东西吗?如果有更好的方法,我很乐意修改。

编辑1 :继续以下讨论之后,我修改了以下内容:

  • 删除了Onclick的{​​{1}}事件属性;
  • 按照以下建议设置ButtonItemCommandName,并更新CommandArgument以使用RowID,它是数据中的唯一ID;
  • DataKeyNames分配了RowCommand个活动;
  • 将删除代码分配给GridView事件。

执行这些更改后,它仍会在第二次单击时触发行事件代码。

编辑2 :仅供参考 - 我现在已删除RowCommand及相关代码/引用,并创建了一个填充数据集的过程,该过程在{{1}上调用}(在SqlDataSource括号内)。我开始在下面进行更改以使用Page_Load事件,但它们仍会导致相同的问题(即按钮只会在第二次点击时触发)。使用!Page.IsPostBack意味着将RowCommand转换为RowCommand s,我又回到了按钮点击事件,因为它似乎毫无意义地使所有这些更改无法获得。如果其他人可以帮助我理解为什么它只在第二次点击时触发,那么将非常感谢您的意见。

2 个答案:

答案 0 :(得分:3)

好的,令人沮丧的是,这是由于某些代码原因尚不清楚,在其他地方有效 在DataBound事件中,有两行代码:

        // get the associate name for the selected record...
        var selectedId = DataBinder.Eval(e.Row.DataItem, "RowID").ToString();
        // create unique row ID...
        e.Row.ID = string.Format("ExtUserRow{0}", selectedId);  

以编程方式将ID应用于行的过程似乎打破了数据与事件之间的联系 通过删除这两行代码,它可以按预期工作。

答案 1 :(得分:-1)

相反,你可以做这样的事情。

像这样向CommandName添加GridView媒体资源。另请注意CommandArgument属性中的更改:

<asp:TemplateField>
    <ItemTemplate>
        <asp:Button runat="server" CssClass="additionsRow" ID="btnDeleteExtUser"  
                    CausesValidation="False" Text="Delete" 
                    CommandName="OnDelete"  
                    CommandArgument='<%# Container.DisplayIndex %>" '                              
</ItemTemplate>
</asp:TemplateField>

背后的代码看起来像这样。请注意,我使用RowCommand的{​​{1}}事件。

Gridview

注意:在protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e) { if(e.CommandName == "OnDelete") { int rowIndex = Convert.ToInt32(e.CommandArgument); // now you got the rowindex, write your deleting logic here. int ID = Convert.ToInt32(myGrid.DataKeys[rowIndex]["ID"].Value); // id will return you the id of the row you want to delete TextBox tb = (TextBox)GridView1.Rows[rowIndex].FindControl("textboxid"); string text = tb.Text; // This way you can find and fetch the properties of controls inside a `GridView`. Just that it should be within `ItemTemplate`. } } 中提及DataKeyNames="ID"。 &#34; ID&#34;是表格的主键列。

您是否在页面加载上绑定了GridView?如果是,请将其移至GridView块,如下所示:

!IsPostBack