I am not sure whether this behavior is documented somewhere, so I simply tell you from my recent programming adventure 😉
In a FormView, I usually arrange the controls inside EditItemTemplate in a table. In this particular case, only selected fields should be edited, depending on some kind of status information.
Since each field (plus prompt) occupies a single row in the table, my choice was straightforward to declare the dynamic table rows as
<tr runat="server" id="trSomething">
However, the form behaved strangely, namely it did not retrieve the control values bound with Bind() into the UpdateCommand’s parameter collection.
To debug, I added Updated and Updating events to the SqlDataSource, and a ItemUpdating event to the FormView, where the NewValues collection of FormViewUpdateEventArgs always gave me an empty dictionary.
I dug further into the generated code somewhere below the Temporary ASP.Net Files directory, and found that no code was generated to retrieve the control values into a dictionary, which should happen during a Bind in Update.
Then I realized that somehow a control bound for update must never be inside any other control marked as Run As Server Control. And indeed, removing the runat tag resolved the mystery.
So if you have controls inside a FormView which are to be displayed or hidden depending the state of a record, you have to hide or display them one by one, as rearranging tables dynamically will break your database functionality.