fixed it. dynamic control must be created and added in Init event. It must be assigned an ID without special ASP.NET symbols ('$' or ':' inside custom ID will break things). All properties must be assigned after control is added to the controls tree.
here's a working example for Page codebehind:
private readonly TextBox _textBoxTest = new TextBox();
protected void Page_Init( object sender, EventArgs e )
{
this.form1.Controls.Add( _textBoxTest );
_textBoxTest.Text = "TestBoxTest";
_textBoxTest.ID = "TestBoxTestId";
_textBoxTest.TextChanged += this._textBoxTest_TextChanged;
}
void _textBoxTest_TextChanged( object sender, EventArgs e )
{
_textBoxTest.Text = "Worked";
}
for WebControl place init code in OnInit override