I have a few different custom controls that extend from different web controls:
RulesPanel: Panel
contains aTable
and a few other controls. TheTable
is populated dynamically with a variable number ofRuleRow
objects. The other controls include ways to increase the number of rows.RuleRow: TableRow
contains threeRuleCell
objectsRuleCell: TableCell
contains aPanel
which is populated dynamically with a variable number ofRuleData
controls. It also contains a few other controls outside of the panel, which are used to increase the number of controls inside the panel.RuleData
: a control extending fromTable
that contains a fixed number of cells and controls.
For RulesPanel
, I want to save the number of rows it has to the control state. For RulesCell
, I want to save the number of controls it has inside its panel. I did it something like this for both (using a table instead of a panel for RulesPanel
):
protected override void OnInit(EventArgs e)
{
Page.RegisterRequiresControlState(this);
base.OnInit(e);
}
protected override object SaveControlState()
{
return new Pair(base.SaveControlState(), pnlChildren.Controls.Count);
}
protected override void LoadControlState(object savedState)
{
Pair controlState = savedState as Pair;
base.LoadControlState(controlState.First);
if ((Int32)controlState.Second > pnlChildren.Controls.Count)
{
AddChildren((Int32)controlState.Second - pnlChildren.Controls.Count);
}
}
Edit: Here is the event handler and the AddChildren function it calls for the RuleCell
class. The RulesPanel
has a similar set of methods, but it adds RuleRow
objects to its table rather than RuleData
objects to a panel.
protected void btnNeedMore_click(object sender, EventArgs e)
{
Int32 numToAdd;
if (Int32.TryParse(txtNeedMore.Text, out numToAdd))
{
AddChildren(numToAdd);
txtNeedMore.Text = "";
}
}
private void AddChildren(Int32 numberToAdd)
{
Int32 totalNumber = pnlChildren.Controls.Count + numberToAdd;
for (Int32 i = pnlChildren.Controls.Count; i < totalNumber; i++)
{
pnlChildren.Controls.Add(new RuleData(i));
}
}
The RuleCell
objects behave correctly. However, when I add more RuleRow
objects to a RulesPanel
(via a postback event from clicking a button), the next postback will cause a "Collection was modified" exception outside of the reach of the VS2012 debugger, just like here.
Collection was modified; enumeration operation may not execute.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[InvalidOperationException: Collection was modified; enumeration operation may not execute.]
System.Collections.HashtableEnumerator.MoveNext() +10715184
System.Web.UI.Page.LoadAllState() +292
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1849
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.18055
Why?