2

I'm really struggling with this. The problem is only with the content pages.
I am trying to access a Text Box value from one content page ("Page1.aspx") in another content page ("Page2.aspx"). I'm not sure whether it is relevant that they are the children of nested master pages, but I thought I'd throw it in.

Page1.aspx is a basic form with text boxes and a submit button. The text box in Page1.aspx is called "tbFirst". The submit button has the following code:

<asp:Button ID="Button1" runat="server" Text="New Member Form" PostBackUrl="Page2.aspx"/>    

Page2.aspx is a new form which should be populated with a textbox value from the previous page. The second line show <%@ PreviousPageType VirtualPath="~/Page1.aspx" %>
For testing purposes I am using a label ("lblResult") to display my results.

Codebehind looks like this:

        if (PreviousPage != null)
        {
            TextBox SourceTextBox =
                (TextBox)PreviousPage.FindControl("tbFirst");
            if (SourceTextBox != null)
            {
                lblResult.Text = SourceTextBox.Text;
            }
            else
            {
                lblResult.Text = "No text found";
            }  
        }
        else
            {
            lblResult.Text = "No Control found";
            }
        }
        }

The problem is that the label text in Page2.aspx says "No text found".

I think that's all the relevant info. Anyone got any ideas? I've spent the whole afternoon trawling the forums and nothing I've tried works.

bjh
  • 59
  • 2
  • 10

2 Answers2

3

I'm not sure whether it is relevant that they are the children of nested master pages, but I thought I'd throw it in.

The MasterPage is exactly what's causing this issue. You cannot find a control on a page with MasterPage by using Page.FindControl("ControlID"), because the Page is not the NamingContainer of the TextBox but the ContentPlaceholder. The only control in the page's ControlCollection with MasterPage is the MasterPage itself.

Reason: I've recently answered a question that describes this behaviour.

Here are some ways how you can access the TextBox from Page2:

  1. You might have luck with following approach(the most direct FindControl way):

    Page.Master.FindControl("ContentPlaceHolder1").FindControl("tbFirst");
    
  2. Another, better approach would be to provide a public property in Page1 that returns tbFirst.Text. Then you could access it in the following way from Page2:

    if (PreviousPage != null && PreviousPage is Page1){
        lblResult.Text = ((Page1)PreviousPage).TbFirstText;
    }
    
  3. You could also add the Text as URL-Parameter, so that it's not required that Page2's PreviousPage is Page1.

  4. Last but not least. If you use Server.Transer with preserveForm set to tue, you would be able to retrieve the value of the original page TextBox control by referencing Request.Form("TbFirst").

Note: I don't recommend a recursive FindControl approach(starting from MasterPage), because it would also hardwire both pages and would be

  • a cause of nasty errors
  • slow
  • untransparent
Community
  • 1
  • 1
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • 1
    Thanks - there are a number of juicy ideas there, I'll need to sleep first and then give it a try! – bjh Jan 08 '12 at 22:24
  • Thanks Tim. 1st (solution and variations) had already been tried many times unsuccessfully. – bjh Jan 09 '12 at 09:43
  • Thanks @Tim. 1st solution (and variations) had already been tried many times unsuccessfully. Solution 2 worked brilliantly with 3, the URL parameter. Found details of each of these solutions in [How to: Pass Values Between ASP.NET Web Pages](http://msdn.microsoft.com/en-us/library/6c3yckfw.aspx) but was getting stuck trying to get one of the solutions to work. Thanks for providing clarity :-) – bjh Jan 09 '12 at 09:50
  • @TimSchmelter way better than my answer. I'm bowing out gracefully – Crab Bucket Jan 09 '12 at 10:01
  • What if I want to access a control from the content page from the MasterPage? – Si8 Aug 19 '14 at 20:36
  • @SiKni8: do you really want to hardwire the `MasterPage` with _one_ content-page? You could use: `MyPage page = Page as MyPage; if(page!=null){}` in the master to check if the current content-page is your specific page(here `MyPage`). Then you just need to provide a public property with a meaningful name in the page which f.e. gets/sets the `Text` property of a `TextBox` (i discourage from exposing a complete control but only the property you need). – Tim Schmelter Aug 19 '14 at 20:45
0

Try using FindControlRecursive(this.Master, "tbFirst") from this class.

(Put this class in App_Code)

using System.Web;
using System;
using System.Web.UI;
using System.Web.UI.WebControls;


/// <summary>
/// Summary description for ControlHelper
/// </summary>
public static class ControlHelper
{
    // Example: HtmlForm form = ControlHelper.FindControlRecursive(this.Master, "form1") as HtmlForm;
    /// <summary>
    /// Finds a Control recursively. Note finds the first match and exits
    /// </summary>
    /// <param name="ContainerCtl"></param>
    /// <param name="IdToFind"></param>
    /// <returns></returns>
    public static Control FindControlRecursive(this Control Root, string Id)
    {
        if (Root.ID == Id)
            return Root;

        foreach (Control Ctl in Root.Controls)
        {
            Control FoundCtl = FindControlRecursive(Ctl, Id);
            if (FoundCtl != null)
                return FoundCtl;
        }

        return null;
    }

    //ModifyControl<TextBox>(this, tb => tb.Text = "test");
    public static void ModifyControl<T>(this Control root, Action<T> action) where T : Control
    {
        if (root is T)
            action((T)root);
        foreach (Control control in root.Controls)
            ModifyControl<T>(control, action);
    }
}
Chuck Savage
  • 11,775
  • 6
  • 49
  • 69