This may be a silly situation and a bit of a lengthy read, but I hope someone may have some tips regarding my issue.
Long story short, I have a situation where I am storing a decision-tree like data in JSON format in a ViewState field, and I dynamically generate Buttons to allow the users to edit this decision-tree (add/change/remove steps, etc).
Everything is mostly fine, but upon PostBacks I have an issue where the dynamic ID of the generated Buttons changes. The reason for that is the life cycle and that way the Buttons get generated twice. The life cycle goes as this:
- PageLoad: Decision tree loaded from ViewState, Buttons get rendered for each step in decision tree. The dynamically generated ID for the Buttons will be like MainContent$ctl02, MainContent$ctl03, MainContent$ctl04, etc.
- PostBack: do any changes to the decision tree (add/change/remove step), this will result in a postback
- PageLoad again: since the event handling generated a postback,the previous Buttons disappear, so in PageLoad I regenerate the Buttons again. But since this happens before the actual button event handler, the data in the ViewState is unaffected, the changes in the decision tree will not be visible yet. The dynamically generated ID for the Buttons will be the same again, MainContent$ctl02, MainContent$ctl03, MainContent$ctl04, etc.
- Button event handler: the part where the changes you wanted to do actually get applied to the decision tree in the ViewState. So to refresh the already rendered decision tree, I clear all the Buttons manually and re-render them, now with the updated decision tree data. The problem is, even though the previous buttons have been cleared/disposed of, the IDs for the new Buttons will get generated where the numbering left off. So the new IDs will be MainContent$ctl05, MainContent$ctl06, MainContent$ctl07, etc.
- The changed IDs are a problem, because now if I click any of the Buttons again (to do further changes), the cycle repeats, the postback disposes of all the dynamically generated Buttons and the PageLoad generates them again, now with the original IDs once again, MainContent$ctl02, MainContent$ctl03, MainContent$ctl04, etc. As a result, your button click event will not get registered, because you clicked MainContent$ctl06, but it no longer exists.
- If you know click again, it will work as expected, because by this point you have the updated decision tree rendered on PostBack with the correct IDs.
So the problem seems to stem from the fact that PageLoad happens before the Button event handler, so I have to render the Buttons twice when making manipulations. PageLoad does it automatically, then Button event changes the data, so need to re-render the Buttons to show the changes. But the system seems to remember the IDs generated on PageLoad. When re-rendering the tree, my goal would be to completely clear the IDs generated on PageLoad, so when I re-render in the Button click event, they are the same as the PageLoad generated IDs.
So far I tried simply with Controls.Clear() or Control.Dispose(), but neither of them seemed to work. While the control visibly disappears, the ID must remain stored somewhere, because the newly generated IDs will be different.
So for example how do I dispose of MainContent$ctl02, so when I create a new Button, it will be once again called MainContent$ctl02?
Okay, after further attempts, I seemed to have solved the issue by using ClienIDMode.Static on each generated Buttons and setting the IDs myself (using the path of the JSON nodes of the steps as ID).
Hopefully this will work in the long run.
But I still wonder if the original issue can be prevented somehow?