Access Textbox on Page from User Control in ASP.net
Asked Answered
T

4

10

I have a some pages that are slightly different, but all have the same "action buttons" that do the same tasks for each page. Instead of duplicating the code, I made a user control that includes buttons that perform actions - but there's one action I can't seem to do.

Each page has a textbox (that's not inside the user control, as it's in a different location of the page). When I click the "Save comment" button (that is within the User Control), I can't seem to access the text in the Textbox.

I have tried using something like this:

TextBox txtComments = (TextBox)this.Parent.FindControl("txtComments");
SaveChanges(txtComments.Text);

...but txtComments comes back as null.

So, I'm wondering if this is possible, or perhaps if there's a better way to do what I'm trying to do?

Edit: The Textbox is in a Placeholder on the original page...

Edit 2: Posting minified solution - still can't figure this one out.

Edit 3: Removed solution to conserve space - resolved the issue.

Tokay answered 7/3, 2013 at 15:45 Comment(5)
Sorry to remind you, but are you passing the correct ID of TextBox to FindControl(...)? Otherwise the same is working fine for me, when i handle the button click event inside the codebehind of UserControl where the Save Button resides, while the TextBox stays on the main Page.Mintamintage
I've checked it over and again a bunch of times! Would it matter that the textbox is in a PlaceHolder control (which shows/hides visibility of it - and other items)?Tokay
As a side note, if you have a CheckBoxList on your page and FindControl hits it, it will always return null.Giuseppinagiustina
@Giuseppinagiustina - in what version of .net? I am running a 4.5 app and FindControl() had no issue with a CheckBoxList, FYI; it did not return null.Bannockburn
Sorry I did not write that correctly. It should say when FindControl hits a CheckBoxList, CheckBoxList always returns itself. In order to accommodate for this, you have to make sure that the control returned by FindControl has the ID that you were looking for. More info here: weblogs.aspnet05.orcsweb.com/scottcate/archive/2005/08/04/…Giuseppinagiustina
T
8

My solution ended up being surprisingly simple....

TextBox txt = this.Parent.Parent.FindControl("ContentPlaceHolder2").FindControl("TextBox1") as TextBox;
if (txt != null) Label1.Text = txt.Text;

Where I was going wrong before was that I was using the wrong ContentPlaceHolder ID. I was using the ID of the placeholder in the page, rather than the ID from the Master Page.

Tokay answered 13/3, 2013 at 14:54 Comment(0)
A
1

Use the Page property exposed by WebControl, the common base of server-side controls.

You could even then cast the instance to the specific page type and access the control directly (if scope allows), instead of using FindControl.

Amy answered 7/3, 2013 at 15:48 Comment(5)
Can you clarify this? I have previously tried Page.FindControl with no success...Tokay
Please look at the msdn documentation: msdn.microsoft.com/en-us/library/31hxzsdw(v=vs.90).aspxHagi
I understand how to use Page.FindControl, but for some reason, my textbox isn't being found - and I'm not sure why.Tokay
Is the textbox directly on the page, or is it in another control like a panel? FindControl isn't recursive, so Page.FindControl() won't find a control that's declared in another control and not directly on the page.Bannockburn
So I added a Page.FindControl("placeholderID") to find the placeholder - but even that is returning null...Tokay
B
1

To recap the situation - you need to do a FindControl of a control on a page from a child control, however -

  1. Your project has a MasterPage, in which case this.Page seems to not work, and we use this.Parent instead
  2. Your "target" control is inside a PlaceHolder, which itself is inside a ContentPlaceHolder, so it's not as simple as just this.Parent.FindControl()
  3. Your child ASCX control that is trying to find the "target" control, in this case a textbox, is actually in ANOTHER ContentPlaceHolder, so again, this.Parent.Parent or whatever will not work.

Since you mentioned after my initial this.Parent answer about the controls being in a different ContentPlaceHolder from each other, and in another child control, it complicates your query a bit.

Based on these criteria, and the fact that you at least know the contentPlaceHolder control which contains (somewhere inside of it) your target TextBox, here's some code I wrote that works for me in a new ASP.net Web Forms application:

It recursively checks controls collection of the ContentPlaceHolder you pass to it, and finds your control.

Just pass the ControlID and ContentPlaceHolderID, and it will recursively find it.

This code is a replacement for my original one below with the same project, located inside of ChildControl.ascx.cs file:

using System; using System.Web.UI; using System.Web.UI.WebControls; using System.Linq; using System.Collections.Generic;

namespace FindControlTest
{
    public partial class ChildControl : System.Web.UI.UserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            var textBoxTest = FindControlInContentPlaceHolder("TextBoxTest", "FeaturedContent") as TextBox;

            Response.Write(textBoxTest.Text);
            Response.End();
        }

        private Control FindControlInContentPlaceHolder(string controlID, string contentPlaceHolderID)
        {
            if (null == this.Page ||
                null == this.Page.Master)
            {
                return null;
            }

            var contentPlaceHolder = this.Page.Master.FindControl(contentPlaceHolderID);
            var control = getChildControl(controlID, contentPlaceHolder);
            return control;
        }

        private Control getChildControl(string controlID, Control currentControl)
        {
            if (currentControl.HasControls())
            {
                foreach(Control childControl in currentControl.Controls)
                {
                    var foundControl = childControl.FindControl(controlID);
                    if (null != foundControl)
                    {
                        return foundControl;
                    }
                    else
                    {
                        return getChildControl(controlID, childControl);
                    }
                }
            }

            return null;
        }
    }
}

Note:

I tried this in a few events and even on Init() I was able to get the TextBox value If you are seeing a null it is likely due to an incorrect ID being passed or a situation I didn't encounter yet. If you edit your question with additional info (as there has been a lot of it) and show what variable is null, it can be resolved.

Note that I added some complexity to my MasterPage, such as a PlaceHolder inside a Panel, and then put the ContentPlaceHolder in there, and the code still works. I even compiled for .net 4.5, 4.0, 3.5, and 3.0 thinking maybe FindControl works differently with MasterPages, but still it works every time. You may need to post some additional MarkUp if you still get a null.

The Rest of the Test Project

The Page (based on default MasterPage)

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="FindControlTest._Default" %>
<%@ Register TagName="ChildControl" TagPrefix="uc1" Src="~/ChildControl.ascx" %>

<asp:Content runat="server" ContentPlaceHolderID="FeaturedContent">

    <asp:PlaceHolder ID="PlaceHolderTest" runat="server">
        <asp:TextBox ID="TextBoxTest" Text="Hello!" runat="server"/>
    </asp:PlaceHolder>

</asp:Content>
<asp:Content ContentPlaceHolderID="MainContent" runat="server">

    <uc1:ChildControl id="ChildControlTest" runat="server" />

</asp:Content>

I added a control called ChildControl.ascx that only has this in it:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ChildControl.ascx.cs" Inherits="FindControlTest.ChildControl" %>
Hello child!

The result is "Hello!" on the page.

Bannockburn answered 7/3, 2013 at 17:4 Comment(8)
This definitely makes sense... and by using debug, I'm getting closer... but another snag? My user control and textbox are in different ContentPlaceHolders in the page (yes, I'm using master pages). Will try to use this technique to go one element deeper...Tokay
That makes it more tricky, I am going to update my answer shortly that will let you find the control from any ContentPlaceHolder.Bannockburn
@Tokay I updated this answer to recursively find control if you pass control ID and ContentPlaceHolderID, this should work for your situation.Bannockburn
For this line - var contentPlaceHolder = this.Page.Master.FindControl(contentPlaceHolderID); - I keep getting a value of null returned. I've triple checked the ID, and still can't get things working...Tokay
@Tokay you need to pass the actual contentplaceholderID to the function, what value are you passing and what is the ContentPlaceholderID (not the ID) of the ContentPlaceHolder that contains your TextBox?Bannockburn
<asp:Content ID="Main" ContentPlaceHolderID="Main" runat="server"> and my function calls: string msg = FindCoordinatorNotes("txtCoordintorNotes", "Main"); which passes "Main" to the contentPlaceHolderID...Tokay
Ok last thing, are you calling this on page load, or somewhere else, if so, where?Bannockburn
let us continue this discussion in chatBannockburn
T
0

If you want to access the textbox property in codebehind as intellisence property, simply make it a string property in the user control.

1. In the user control, create a public string property that returns textbox string value..

public string MyText
{
get
{
return txt1.Text;
}
}

2. Register the user control on the page

<%@ Register TagPrefix="uc" TagName="MyControl" Src="~/mycontrol.ascx" />

and declare it..

<uc:MyControl ID="control1" runat="server" />

3. From the codebehind now you can read the property..

Response.Write(control1.MyText);

Hope it helps

Thanks...
Trope answered 8/6, 2018 at 6:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.