Found this from another source. Makes sense but I wasn't completely versed in the lifecycle or behavior of the aspx page.
You will not be able to render server side controls using string representation of the control. That approach works for plain HTML controls. But, server side controls need to go through a rendering mechanism which will not be invoked when you just set text property of a control. Better alternative would be keeping just one panel in the item template and adding controls dynamically in the itemdatabound event based on conditions. Then, You can check if some condition is true and then add textbox or a button accordingly. If there are too many controls, you can also use UserControls. But, dynamic controls will not be retained across page postbacks and you would need to add them back with the same ID. If you do not want to handle all this creation mechanism, you could just keep two independent panels and update the visibility based on some conditions.
within Listview :
<td>
<asp:Panel runat="server" ID="pnlOne" Visible='<%# CanShowFirstPanel()%>'>
<asp:Button ID="Button1" runat="server" Text="Button" />
</asp:Panel>
<asp:Panel runat="server" ID="pnlTwo" Visible='<%# CanShowSecondPanel()%>'>
<asp:TextBox runat="server" ID="TextBox1" />
</asp:Panel>
</td>
Code-behind:
Public Function CanShowFirstPanel() As Boolean
'condition to check
Return True
End Function
Public Function CanShowSecondPanel() As Boolean
'condition to check
Return False
End Function