情况:我在一个页面上有几个Gridview,每个Gridview都有一个动态创建的行来显示底部的总计。在每种情况下,在RowDataBound事件上创建总计行。我使用的策略类似于Mike Dugan在Blog上提供的策略。
以下是其中一个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);
}
问题:如果用户点击任何这些网格视图上的任何行的编辑/删除命令,它将使所有其他网格视图的总计行消失。据我了解,这是因为发生了PostBack,但是其他GridViews不会发生RowDataBound事件,而是只会从ViewState重新加载它们的数据,而ViewState不包含总数。
尝试解决失败:我不能简单地在PostBack期间在每个GridView上调用DataBind,因为这样可以防止更新/删除。虽然在PostBack期间GridViews会发生RowCreated事件,但这个事件还不够,因为GridViews不会绑定数据,并且在我尝试计算总数时会抛出异常。禁用这些GridView的ViewState似乎是一种解决方案,但每次用户单击命令时都会有大量数据需要重新加载。手动将我的数据保存到ViewState似乎也是一个解决方案,但似乎没有一种简单的方法让GridViews在PostBack上检索这些自定义数据。
有没有办法真正实现我想用ASP.NET做的事情?在每个GridView的底部都有一个总计行似乎是一个简单的要求。
提前感谢您的帮助。
答案 0 :(得分:0)
如果您尝试使用gridView.OnPreRender
事件而不是gridView.RowDataBound
事件创建动态行,该怎么办?这样,您可以使用计算动态行结果所需的数据,但html尚未发送到Web浏览器。请发布更多代码,以便我们提供更多洞察力来解决您的问题。
答案 1 :(得分: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);
}
答案 2 :(得分: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);
}
}