动态创建的行在更新/删除时从 Gridview 中消失
情况:我在一个页面上有多个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 的总计行消失。据我了解,这是因为正在发生 PostBack,但是其他 GridView 不会发生 RowDataBound 事件,而是它们只会从 ViewState 重新加载数据,而 ViewState 不包含总计。
尝试解决失败:我不能在回发期间简单地在每个 GridView 上调用 DataBind,因为这会阻止更新/删除的发生。尽管在回发期间 GridView 会发生 RowCreated 事件,但该事件还不够,因为 GridView 不会绑定数据,并且当我尝试计算总数时会引发异常。禁用这些 GridView 的 ViewState 似乎是一个解决方案,但是每次用户单击命令时都会重新加载大量数据。手动将数据保存到 ViewState 似乎也是一种解决方案,但似乎没有一种简单的方法可以让 GridView 在 PostBack 上检索此自定义数据。
有什么方法可以真正实现我想要使用 ASP.NET 做的事情吗?在每个 GridView 底部都有一个总计行似乎是一个简单的要求。
预先感谢您的任何帮助。
Situation: I have several Gridviews on one page, and each Gridview has a dynamically created row to display the totals at the bottom. In each case, the totals row is created on a RowDataBound event. The strategy that I am using is like the one provided by Mike Dugan on his Blog.
The following is the code for one of the GridViews, but the others all do something very simular.
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);
}
Problem: If a user clicks on an edit/delete command for any row on any of these Gridviews, it will make the totals row disappear for all other Gridviews. As I understand, this is because a PostBack is occurring, however the RowDataBound events will not occur for the other GridViews, rather they will just reload their data from the ViewState, which does not contain the totals.
Failed attempts at solving: I cannot simply call DataBind on each of the GridView during a PostBack, because that will prevent the update/delete from occurring. Although the RowCreated event will occur for the GridViews during a PostBack, this event in not sufficient because the GridViews will not have data bound and will throw an exception when I try to calculate the total. Disabling the ViewState for these GridViews seems like a solution, however there will be a lot of data to reload each time a user clicks a command. Manually saving my data to the ViewState also seems like a solution, but there does not seem to be a simple way to have the GridViews retrieve this custom data on a PostBack.
Is there any way to actually achieve what I am trying to do with ASP.NET? It seems like a simple requirement to have a totals row at the bottom of each GridView.
Thanks in advance for any help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您尝试使用
gridView.OnPreRender
事件而不是gridView.RowDataBound
事件创建动态行,会怎样?这样,计算动态行结果所需的数据就可用,但 html 尚未发送到 Web 浏览器。请发布更多代码,以便我们提供更深入的见解来解决您的问题。What if you try creating the dynamic row using the
gridView.OnPreRender
event instead of thegridView.RowDataBound
event. This way your data you need to calculate your dynaimic row results is available but the html has not been sent to the web browser yet. Please post some more code so we can provide more insight into fixing your issue.按照建议,我尝试将代码放在 PreRender 事件而不是 RowDataBound 事件中创建总计行。这似乎有效,只是它破坏了它所使用的 GridView 的所有命令。看来手动更改 GridView 会破坏其自动行为。
As recommended, I tried putting the code to create the totals row in the PreRender event rather than the RowDataBound event. This seemed to work, except that it broke all of the commands for the GridView that it was used on. It appears that manually changing the GridView disrupts its automatic behavior.
好的,我最终解决这个问题的方法是使用 JQuery。如果其他人面临类似的问题,请记住,必须在 DOM 准备好时以及任何回发结束时计算总数。要处理回发情况,您只需使用 ScriptManager.RegisterStartupScript() 调用客户端上的 Javascript。
同样,在我的情况下有四个 GridView,但我将只显示其中之一的 JQuery 代码:
对于后面代码中的 C#:
OK, the way I ended up solving this was with JQuery. If anybody else is facing a similar problem, remember that the totals must be calculated when the DOM is ready, as well as at the end of any postback. To handle the postback situation, you can just call the Javascript on the client using ScriptManager.RegisterStartupScript().
Again, I had four GridViews in my circumstance, but I'll just show the JQuery code for one of them:
And for the C# on the code behind: