Today when doing some application building I came across a case where I wanted to embed a ASP control inside one of the template of the asp:ListView control. This is legal and simple todo, however it has some interesting effects. Since the control is embedded in a template it is not made available in the code behind file and in my case I wanted to be able to access the control in the code behind file. Here is an example of what my markup looked like:
<asp:ListView ID="ListView1" runat="server"> <LayoutTemplate> <table> <tr> <td><asp:PlaceHolder ID="ItemPlaceHolder" runat="server"></asp:PlaceHolder></td> </tr> <tr> <td> <asp:Button ID="ButtonTest" runat="server" Text="Button" /> </td> </tr> </table> </LayoutTemplate> </asp:ListView>
I searched the Internet for a solution to this problem and many of the common solutions to the problem I found where to hooked to ItemCreated or DataBound event from the ListView, then using FindControl to find the control and store it in a variable that was part of the page class. While this is entirely doable it leads to really clunky code and there is a much better method for doing this. Controls have the same life cycle methods that the page itself has an by handling the Init event for the button I can get access to the button as soon as it is created and store a copy off that can be used when other parts of the page fire events.
Here is the change to the markup above:
<asp:Button ID="ButtonTest" runat="server" Text="Button" oninit="ButtonTest_Init" />
And here is what the code behind looks like:
public partial class _Default : System.Web.UI.Page { Button ButtonTest; protected void ButtonTest_Init(object sender, EventArgs e) { ButtonTest = (Button)sender; ButtonTest.Text = "Foo"; } protected void ListView1_ItemDeleted(object sender, ListViewDeletedEventArgs e) { ButtonTest.Text = "Add"; } }
The ButtonTest_Init event handler stores the button in ButtonTest and changes it's text. You will also note that because I've done this I can now access the button inside other event handlers the ListView may fire, which was my initial goal. All in a very clean manner not hooking ListView events and not calling FindControl.