This took a lot of achieving. I read internet pages for more than a day before coming up with the following:
Contrary to what a LOT of forums say, where you must recreate all controls on the OnInit override, you dont have to. What you must do is this:
1. Set OnInit to do the following:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
Page.RegisterRequiresControlState(this);
... Your other on init code
}
This forces the Control State memory bank to be turned on.
2. Go to the routine where you are creating the controls, and specify the ID of the buttons. If you do not, you will not be able to complete stage 3.
Button btn = new Button();
btn.ID = "btnProg" + prog.ProgId.ToString();
btn.Click += new EventHandler(SelectProgramme_click);
tcInfo.Controls.Add(btn);
hplProgrammeLinks.Add(btn);
3. Create/Edit the Page Load to reconstruct your controls which will no longer exist. They must have the SAME IDs, so I call the same routine that generated them in the first place. The page_load does work because it occurs in the page lifecycle BEFORE the events are fired. If the IDs are inconsistent your events will vanish. This will cause an unintended side effect where your routine for generation is called OnLoad and then again with the page events. If you do need data reads etc, put them into properties in a seperate routine, and have the object generation called seperately.
if (Page.IsPostBack) && (!String.IsNullOrEmpty(SearchString.Text))
{
doSearch(1);
}