2

情况:我在一页上有几个 Gridview,每个 Gridview 都有一个动态创建的行来显示底部的总数。在每种情况下,总计行都是在 RowDataBound 事件上创建的。我使用的策略类似于 Mike Dugan 在他的博客上提供的策略上提供的策略。

以下是其中一个 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 的总计行消失。据我了解,这是因为正在发生 PostBack,但是其他 GridViews 不会发生 RowDataBound 事件,它们只会从不包含总数的 ViewState 重新加载数据。

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

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

提前感谢您的帮助。

4

3 回答 3

0

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

于 2011-12-15T21:13:41.743 回答
0

好的,我最终解决这个问题的方法是使用 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);
    }
}
于 2012-01-04T21:41:17.507 回答
0

按照建议,我尝试将用于创建总计行的代码放在 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);
}
于 2011-12-16T16:09:59.770 回答