1

在询问之前我已经进行了一些搜索,虽然这篇文章很接近,但它不适用于我的场景。

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

所以,分解代码,我将我的数据绑定到一个GridView,使用一个 `SqlDataSource.

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

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

只需将onclickAddConfirmMessage属性分配给控件以确保用户必须确认删除。

现在,在每种情况下,都会弹出消息' OK to delete 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事件属性ButtonItem
  • 按照下面的建议设置CommandNameand CommandArgument,并更新DataKeyNames以使用 RowID,这是数据中的唯一 ID;
  • 为; 分配了一个RowCommand事件GridView
  • 将删除代码分配给RowCommand事件。

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

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

4

2 回答 2

3

OK, frustratingly this was due to some code that for reasons still unknown, works elsewhere.
In the DataBound event, there was two lines of code:

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

The process of applying an ID to the rows programatically seems to break the connection between the data and the events.
By removing these two lines of code, it works as expected.

于 2013-03-04T18:00:48.323 回答
-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使用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"在你的GridView. “ID”是表的主键列。

您是否绑定了GridView页面加载?如果是这样,则将其移动到!IsPostBack块,如下所示:

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        GridView1.DataSource = yourDataSource;
        GridView1.DataBind();           
    } 
}
于 2013-03-04T11:30:39.677 回答