Using FindControl: Accessing Controls in a Formview

CJM picture CJM · Oct 22, 2009 · Viewed 14.8k times · Source

I'm developing a simple Wedding List application, where guests can reserve the present they want to buy for the bride and groom. The Reserve page wraps a few fields inside a couple of panels, all wrapped inside a FormView.

The user enters their name, email and the quantity of items that they want to reserve, and the page will make the necessary reservations in the DB.

My first problem was that in FormView_ItemCommand, I couldn't reference any of the other controls in the FormView.... I figured this was a case for FindControl - but why do I need to for a Formview when I've never needed it for ListViews or DetailViews?

Secondly, I know the following code works..

Dim oCtrl as TextBox = Me.fvwReservation.FindControl("txtEmail")
Dim Test As String = oCtrl.Text

...but why can't I use...

Dim Test As String = Me.fvwReservation.FindControl("txtEmail").Text

??

Finally, I don't think I need it on this occasion, but I've been researching recursive FindControl variants, but I haven't actually found one that actually compiles! Any suggestions?

It's a lot for one post - thanks in advance.

Gratuitous Code Snippet:

<asp:FormView ID="fvwReservation" runat="Server" DataSourceID="dsGift">
     <ItemTemplate>
      <asp:Panel runat="server" ID="pnlDetails">
       <h3>Reserve Item: <%#Eval("ShortDesc")%></h3>
       <p>You have chosen to reserve the <em><%#Eval("LongDesc")%></em> gift.</p>
       <p>Please enter your details below to confirm the reservation.</p>
      </asp:Panel>
      <asp:Panel runat="server" ID="pnlConfirm">
       <div class="row">
        <asp:Label runat="server" CssClass="label">Name:</asp:Label><asp:TextBox ID="txtName" MaxLength="50" runat="server" CssClass="Field" />
        <asp:RequiredFieldValidator ID="rfvName" runat="server" ErrorMessage="You must specify your Name" ControlToValidate="txtName" />
       </div>
       <div class="row">
        <asp:Label runat="server" CssClass="label">Email:</asp:Label><asp:TextBox ID="txtEmail" MaxLength="100" runat="server" CssClass="Field"/>
        <asp:RequiredFieldValidator ID="rfvEmail" runat="server" ErrorMessage="You must specify your Email Address" ControlToValidate="txtEmail" />
        <asp:RegularExpressionValidator ID="regexEmail" ValidationExpression="^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6}$" runat="server" ErrorMessage="Please enter a valid Email Address" ControlToValidate="txtEmail" />
       </div>
       <div class="row">
        <asp:Label runat="server" CssClass="label">Quantity (max <%#Eval("QtyRemaining")%>):</asp:Label><asp:TextBox ID="iQty" MaxLength="2" runat="server" CssClass="Field" />
        <asp:RangeValidator ID="rvQty" runat="server" ErrorMessage="The Quantity mmust be between 1 and 10" MinimumValue="1" MaximumValue="10" ControlToValidate="iQty" />
       </div>
       <div class="row">
        <asp:Label runat="server" CssClass="label">&nbsp;</asp:Label>
        <asp:Button ID="btnReserve" Text="Confirm Reservation" CommandName="Reserve" runat="server" />
       </div>
      </asp:Panel>      
     </ItemTemplate>
    </asp:FormView>

Answer

Jason Berkan picture Jason Berkan · Oct 22, 2009

For your second question, FindControl returns a generic Control, and must be cast to the specific type of control in order to obtain access to the properties of that specific type of control.

You can do it in a one liner, like this:

Dim Test As String = CType(Me.fvwReservation.FindControl("txtEmail"), TextBox).Text

Regarding your first question, I would love to know the answer to that as well.

EDIT

Looked through a few other StackOverflow responses (specifically this one and this one). As the controls in the FormView template do not exist until the template is the active template, you cannot directly refer to them in the code behind. Thus, you must use FindControl during an appropriate event to access the controls.