2011-12-15 52 views
2

情况:我在一个页面上有几个GridView,每个Gridview都有一个动态创建的行来显示底部的总数。在每种情况下,总数行都是在RowDataBound事件上创建的。我使用的策略就像由Mike Dugan在他的Blog上提供的策略。动态创建的行从Gridviews上消失更新/删除

下面是一个GridViews的代码,但其他人都做了非常类似的事情。

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正在发生,但是RowDataBound事件不会发生在其他GridView上,而只是从ViewState中重新加载他们的数据,而不包含总数。

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

有没有什么办法来真正实现我想用ASP.NET做什么?这似乎是一个简单的要求,在每个GridView的底部都有一个总计行。

在此先感谢您的帮助。

+0

你有没有看过使用Ajax或更新面板只刷新你想要的? – 2011-12-15 21:01:00

+0

我还没有尝试过使用UpdatePanel,尽管整个页面已经包装在一个UpdatePanel中,因此我可以在PostBacks上保存滚动位置。我会给你一个镜头。 – 2011-12-15 21:53:32

回答

0

好的,我最终解决这个问题的方式是使用JQuery。如果其他人正面临着类似的问题,请记住,当DOM准备好总计必须计算,以及在任何回发的结束。为了处理回发的情况下,你可以调用JavaScript使用ScriptManager.RegisterStartupScript()在客户端上。

同样,我在我的情况下4个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); 
    } 
} 
0

如果尝试使用gridView.OnPreRender事件而不是gridView.RowDataBound事件创建动态行,该怎么办。这样你的数据就可以计算你的dynaimic行结果了,但是html还没有被发送到web浏览器。请张贴更多代码,以便我们提供更多见解来解决您的问题。

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