Asp.net 动态创建的行在更新/删除时从GridView中消失

Asp.net 动态创建的行在更新/删除时从GridView中消失,asp.net,gridview,postback,viewstate,rowdatabound,Asp.net,Gridview,Postback,Viewstate,Rowdatabound,情境:我在一个页面上有几个Gridview,每个Gridview都有一个动态创建的行,在底部显示总计。在每种情况下,总计行都是在RowDataBound事件上创建的。我正在使用的策略就像Mike Dugan在他的 下面是其中一个GridView的代码,但是其他GridView都做一些非常类似的事情 protected void gvWorkerHours_RowDataBound(object sender, GridViewRowEventArgs e) { // Keep runni

情境:我在一个页面上有几个Gridview,每个Gridview都有一个动态创建的行,在底部显示总计。在每种情况下,总计行都是在RowDataBound事件上创建的。我正在使用的策略就像Mike Dugan在他的

下面是其中一个GridView的代码,但是其他GridView都做一些非常类似的事情

protected void gvWorkerHours_RowDataBound(object sender, GridViewRowEventArgs e)
{
    // Keep running total of hours.  
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        totalBillableHours += Convert.ToDouble(DataBinder.Eval(e.Row.DataItem, "Hours"));
    }

    if (e.Row.RowType == DataControlRowType.Footer)
    {
        int numColumns = gvWorkerHours.Columns.Count;
        int hoursIndex = 4; //5th column, 0-based
        int rowIndex = gvWorkerHours.Rows.Count + 1;

        CreateTotalRow((Table)e.Row.Parent, rowIndex, totalBillableHours, hoursIndex, numColumns);
    }
}

private void CreateTotalRow(Table table, int rowIndex, double totalValue, int totalIndex, int numColumns)
{
    TableCell[] cells = new TableCell[numColumns];
    for (int i = 0; i < numColumns; i++)
    {
        TableCell cell = new TableCell();
        Label label = new Label();
        label.Font.Bold = true;

        if (i == 0)
        {
            label.Text = "Total";
        }
        else if (i == totalIndex)
        {
            label.Text = totalValue.ToString();
        }
        else
        {
            label.Text = "";
        }

        cell.Controls.Add(label);
        cells[i] = cell;
    }
    GridViewRow row = new GridViewRow(-1, -1, DataControlRowType.DataRow, DataControlRowState.Normal);
    row.Cells.AddRange(cells);
    table.Rows.AddAt(rowIndex, row);
}
问题:如果用户单击这些GridView中任意一行的编辑/删除命令,则会使所有其他GridView的总计行消失。据我所知,这是因为正在发生回发,但是其他GridView不会发生RowDataBound事件,而只是从不包含总计的ViewState重新加载数据

解决问题的尝试失败:在回发期间,我不能简单地在每个GridView上调用DataBind,因为这将阻止更新/删除的发生。虽然在回发期间GridView将发生RowCreated事件,但此事件并不充分,因为GridView将没有数据绑定,并且在我尝试计算总数时将引发异常。禁用这些GridView的ViewState似乎是一个解决方案,但是每次用户单击命令时都会有大量数据需要重新加载。手动将数据保存到ViewState似乎也是一种解决方案,但似乎没有一种简单的方法让GridView在回发时检索此自定义数据

有什么方法可以真正实现我用ASP.NET所做的事情吗?在每个GridView的底部有一个totals行似乎是一个简单的要求


提前感谢您的帮助

如果尝试使用gridView.OnPreRender事件而不是gridView.RowDataBound事件创建动态行会怎么样。这样,计算dynamic行结果所需的数据可用,但html尚未发送到web浏览器。请发布更多代码,以便我们能够更深入地了解如何解决您的问题。

如果您尝试使用gridView.OnPreRender事件而不是gridView.RowDataBound事件创建动态行,该怎么办。这样,计算dynamic行结果所需的数据可用,但html尚未发送到web浏览器。请发布更多代码,以便我们能够提供更多关于解决问题的见解。

根据建议,我尝试将代码放在PreRender事件而不是RowDataBound事件中创建总计行。这似乎是可行的,只是它破坏了用于GridView的所有命令。手动更改GridView可能会中断其自动行为

protected void gvWorkerHours_PreRender(object sender, EventArgs e)
{
    double total = 0;
    int numColumns = gvWorkerHours.Columns.Count;
    int hoursIndex = 4; //5th column, 0-based
    int rowIndex = gvWorkerHours.Rows.Count + 1;

    foreach (GridViewRow row in gvWorkerHours.Rows)
    {
        if (row.RowType == DataControlRowType.DataRow)
        {
            Label label = (Label)row.FindControl("lblHours");
            total += Convert.ToDouble(label.Text);
        }
    }

    CreateTotalRow((Table)gvWorkerHours.Rows[0].Parent, rowIndex, total, hoursIndex, numColumns);
}

按照建议,我尝试将代码放在PreRender事件而不是RowDataBound事件中创建totals行。这似乎是可行的,只是它破坏了用于GridView的所有命令。手动更改GridView可能会中断其自动行为

protected void gvWorkerHours_PreRender(object sender, EventArgs e)
{
    double total = 0;
    int numColumns = gvWorkerHours.Columns.Count;
    int hoursIndex = 4; //5th column, 0-based
    int rowIndex = gvWorkerHours.Rows.Count + 1;

    foreach (GridViewRow row in gvWorkerHours.Rows)
    {
        if (row.RowType == DataControlRowType.DataRow)
        {
            Label label = (Label)row.FindControl("lblHours");
            total += Convert.ToDouble(label.Text);
        }
    }

    CreateTotalRow((Table)gvWorkerHours.Rows[0].Parent, rowIndex, total, hoursIndex, numColumns);
}

好的,我最终解决这个问题的方法是使用JQuery。如果其他人也面临类似的问题,请记住,必须在DOM就绪时以及在任何回发结束时计算总数。要处理回发情况,只需使用ScriptManager.RegisterStartupScript在客户端上调用Javascript即可

同样,在我的环境中,我有四个GridView,但我只展示其中一个的JQuery代码:

$(document).ready(function () {
    setTotals();
});

function setTotals() {

    var totalHours = getBillableHoursTotal();
    if (isNaN(totalHours)) totalHours = '...editing';
    $('#spanBillableHoursTotal').html(totalHours);

    //... etc.
}

function getBillableHoursTotal() {
    var total = 0.0;
    var rows = $('table[id*="_gvWorkerHours"] tr.RegularRows');
    $(rows).each(function () {
        total = total + parseFloat($(this).children('td').children('span[id*="lblHours"]').html()); 
    });
    return total;
}
对于代码背后的C:

protected void Page_Load(object sender, EventArgs e)
{
    // ... preceeding Page Load code

    if (IsPostBack)
    {
        ScriptManager.RegisterStartupScript(this, this.GetType(), "?", "setTotals()", true);
    }
}

好的,我最终解决这个问题的方法是使用JQuery。如果其他人也面临类似的问题,请记住,必须在DOM就绪时以及在任何回发结束时计算总数。要处理回发情况,只需使用ScriptManager.RegisterStartupScript在客户端上调用Javascript即可

同样,在我的环境中,我有四个GridView,但我只展示其中一个的JQuery代码:

$(document).ready(function () {
    setTotals();
});

function setTotals() {

    var totalHours = getBillableHoursTotal();
    if (isNaN(totalHours)) totalHours = '...editing';
    $('#spanBillableHoursTotal').html(totalHours);

    //... etc.
}

function getBillableHoursTotal() {
    var total = 0.0;
    var rows = $('table[id*="_gvWorkerHours"] tr.RegularRows');
    $(rows).each(function () {
        total = total + parseFloat($(this).children('td').children('span[id*="lblHours"]').html()); 
    });
    return total;
}
对于代码背后的C:

protected void Page_Load(object sender, EventArgs e)
{
    // ... preceeding Page Load code

    if (IsPostBack)
    {
        ScriptManager.RegisterStartupScript(this, this.GetType(), "?", "setTotals()", true);
    }
}

您是否考虑过使用ajax或updatepanel只刷新您想要的内容?我还没有尝试使用updatepanel,尽管整个页面已经包装在updatepanel中,以便在回发时保存滚动位置。我来试一试。尝试将其中一个GridView包装到UpdatePanel中,但当我单击任何其他GridView的命令时,其总计行消失。您是否考虑过使用ajax或UpdatePanel仅刷新所需内容?我还没有尝试使用UpdatePanel,尽管整个页面已经包装在UpdatePanel中,以便我可以在回发时保存滚动位置。我来试一试。尝试将其中一个GridView包装到UpdatePanel中,但当我单击任何其他GridView命令时,它的总计行消失了。感谢您帮助gsirianni。我编辑了我的原始问题,加入了一些代码。我将尝试使用PreRender事件。好的@gsirianni,我尝试在PreRender中执行此操作,但没有成功
断开所有更新、删除、插入命令。我将在另一个答案中发布代码。谢谢你帮助gsirianni。我编辑了我的原始问题,加入了一些代码。我将尝试使用PreRender事件。好的@gsirianni,我尝试在PreRender中执行它,但它破坏了所有的命令update、delete和insert。我将在另一个答案中发布代码。