Page Lifecycle - Using FindControl to reference a

2019-05-22 22:54发布

问题:

I'm creating some text boxes on my form programmatically which I need to reference later using FindControl.

I've put the FindControl instruction in the page load method after the code which creates them but get an error:

Object reference not set to an instance of an object.

I assume this is because the textbox controls are not created until later in the lifecycle and therefore cannot be referenced from within Page_Load.

Can someone advise where in my code-behind I would need to place the FindControl instruction so that it can find these programmatically created text boxes?

回答1:

Did you put your textbox control inside of another control such as a panel or grid? If so you need to recursively search all the controls on the page.

Here is an example of a recursive FindControl implementation: Recursive Page.FindControl. You can find many other examples by googling "recursive findcontrol".



回答2:

If you create textboxes programmatically you can use directly that to manipulate them. No need for FindControl (which would also be slower)

TextBox txt = new TextBox();
...
txt.Text = "Text";

If you need access in different methods you can just make txt a private variable of the class.

If you really need to use FindControl - are the textboxes added in the page (added to the Controls list of the page) when you call the function?



回答3:

At page load time, the controls should all be set up and ready to be used. Controls are initialized and during the Init phase which is before Load phase.

I would recommend you to check the code finding the control to start with - for example, if controls are nested inside other controls, you will need to search recursively or from the correct container control.



回答4:

If you're adding the textboxes in CreateChildControls you may have to call EnsureChildControls before accessing them.



回答5:

just found this function from a blog post by Steele Price and it worked perfectly. I was trying to reference a usercontrol inside a page that had a master page, nothing I tried worked except this. Put it in one of your core classes. Read Steele's blog post for more details.

If you put this in a class you will need to get the control reference like:

Dim imgStep2PreviewIcon As Image = Eyespike.Utilities.FindControl(Of Control)(Page, "imgStep1PreviewIcon")
imgStep2PreviewIcon.Visible = False

VB.NET Code

Public Shadows Function FindControl(ByVal id As String) As Control
    Return FindControl(Of Control)(Page, id)
End Function

Public Shared Shadows Function FindControl(Of T As Control)(ByVal startingControl As Control, ByVal id As String) As T
    Dim found As Control = startingControl
    If (String.IsNullOrEmpty(id) OrElse (found Is Nothing)) Then Return CType(Nothing, T)
    If String.Compare(id, found.ID) = 0 Then Return found
    For Each ctl As Control In startingControl.Controls
        found = FindControl(Of Control)(ctl, id)
        If (found IsNot Nothing) Then Return found
    Next
    Return CType(Nothing, T)
End Function

C# (untested, generated using converter.telerik.com)

public new Control FindControl(string id)
{
    return FindControl<Control>(Page, id);
}

public static new T FindControl<T>(Control startingControl, string id) where T : Control
{
    Control found = startingControl;
    if ((string.IsNullOrEmpty(id) || (found == null))) return (T)null; 
    if (string.Compare(id, found.ID) == 0) return found; 
    foreach (Control ctl in startingControl.Controls) {
        found = FindControl<Control>(ctl, id);
        if ((found != null)) return found; 
    }
    return (T)null;
}


回答6:

If you make your TextBox controls during an OnInit override (before calling base.OnInit(e) I believe) they will be available during Page.OnLoad and any associated events. You also get them into the ViewState object graph in their correct position which is invaluable for dealing with post backs and especially server-side validation.