views:

1353

answers:

3

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>
+3  A: 

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.

Jason Berkan
You see?! I knew I was missing something.... actually, I'm sure I've seen that before, but failed to realise the significance... Have a gold star! (well +1 rep might have to suffice).
CJM
A: 

Hmm, even in the FormView templates, I don't think that FindControl will work reliably, typically I would only use that with straight HTML rendered controls, not ASP.net generated ones.

I'm pretty sure that the templated controls should be available in the Server side code, (ie. txtEmail.text) if not, double check the template

A recursive FindControl is also pretty taxing on the Server and potentially unreliable.

Mark Kadlec
I appreciate the suggestion, but I don't know where I might have gone wrong. Given the code above, in FormView_ItemCommand, none of the controls in the two Panels can be accessed directly.
CJM
That's odd, did you look into the source to see the name of the control, curious why the Server wouldn't be able to recognize...I'm not sure why the controls can't be accessed directly, the FormView is simply a template for a single record if I'm not mistaken, and by declaring each control as an asp.net control should not behave differently than any other declaration.I'll admit I never had to access from within a FormView in code though...
Mark Kadlec
Ahh, just read the above post - good to know!
Mark Kadlec
A: 

You need to use recursive FindControl method in order to access the elements inside the FormView control. There are many implementations available and one of them is linked below:

http://www.highoncoding.com/Articles/606%5FCreating%5Fa%5FBetterFindControl%5Fand%5FMuchBetterFindControl.aspx

azamsharp
I don't need a recursive FindControl (as I mentioned in my OP), but nevertheless, one would be useful for future use. However, I'd prefer a VB version, but I'll try to translate this one...
CJM
Hi, You can use any of the free online translator tools: http://www.developerfusion.com/tools/convert/csharp-to-vb/
azamsharp
Although I didn't need it in this case, I've converted the code mentioned in that article and it seems to work well. Thanks.
CJM