I'm trying to find a label on an aspx page from a user control (ascx) on said aspx page. Obviously Page.FindControl("lablel1") is not working. Do I need to add in ClientID somewhere? Thanks.
I think you ought to stop and think about your design. Your controls should not ever need to know anything about the page that contains them - the fact that you need to go find a control on the page from within another control tells me that you ought to rethink the problem.
The best thing I can tell you (with what little I know of your architecture) is that you ought to pass in a reference to the control you hope to find into your user control. This way your control does not have to know about things outside itself.
When using FindControl()
outside of the context of the control's immediate parent, you will need to walk the control tree to find which level your label
lives in and call .FindControl()
at the appropriate level.
That said, take @Andrew Hare's advice and revisit your architectural decisions. There is likely a better way to have your UserControl interact with its consuming page.
For example, you can expose a public event in your UserControl and add an eventhandler to your consuming page (or base page/masterpage). When creating an event you can make the signature what ever your want, so go ahead and include the error text which needs to get passed.
If you want to get funky with it, you can turn your Error label into a custom control with hooks into the event.
Sample Event:
Public Event UserErrorOccured(ByVal ErrorText as String)
Sample Error:
If Not Page.IsValid Then
RaiseEvent("The page is not valid")
End If
Sample Handler:
protected sub UserEventHandler(ByVal ErrorText as String) Handles MyUserControl.UserErrorOccured
errorLabel.Text = ErrorText
End Sub
Something like this should work if the hierarchy is predictable.
Me.Owner.FindControl("controlName")
or...
Me.Owner.Parent.FindControl("controlName")
or...
Me.Owner.Parent.Parent.FindControl("controlName")
If it's not predictable, then you'll have to write a recursive (expensive) function to find the control instead. Be careful with your approach here though, because this type of algorithm can become slow and unwieldy if overused on large pages.
Here's an example in VB for searching through the tree backwards (from child to parent) and finding a control:
Protected Function FindControlByID(ByRef childControl As Control, ByVal ID As String) As Control
Dim ctrl As Control = childControl.FindControl(ID)
If Not ctrl Is Nothing Then
Return ctrl
Else
If Not childControl.Parent Is Nothing Then
Return FindControlByID(childControl.Parent, ID)
Else
Return Nothing
End If
End If
End Function
I'd call it like this:
Dim lbl As Label = FindControlByID(Me.Owner, "label1")
Of course, on the other hand, this is one of those crappy solutions that when something does change, it'll break and you may not remember why. But that's just a reason to avoid doing this to begin with, if you can - Steve Wortham 2009-06-16 20:19
Create an interface, such as:
public interface IStatusDisplayer
{
Label StatusLabel { get; }
}
Implement the interface on any page that displays the error/status label. If your user control needs to access the label you can do this:
var statusDisplayer = this.Page as IStatusDisplayer;
if (statusDisplayer != null)
{
statusDisplayer.StatusLabel.Text = "Hello World!";
}
From within the user control
Me.NamingContainer.FindControl("label1")
Control ct = WebUserControl11.FindControl("DropDownList1");
DropDownList dt = (DropDownList)ct;
TextBox1.Text = dt.SelectedValue.ToString();
A couple of other ideas come to mind. There is the "Items" collection in the Page class that could be used to store a value or the Session object for a similar thought. Another is to expose a public method on the page to update the label. There may be AJAX issues with that architecture as I'm not sure how well the callback can update multiple areas of a page at the same time, so this is just a warning and I'm not saying I have had this problem.
TheSteve's answer also works and is how I've done it when I had to in the past though it can be tricky tossing around controls. I would also second Andrew's answer though.
This is simple, first you need to access the master page ContentPlaceHolder:
Dim ContentPlaceHolder1 As ContentPlaceHolder = TryCast(Page.Master.FindControl("ContentPlaceHolder1"), ContentPlaceHolder)
Then using the ContentPlaceHolder you can now find the ID of the control on the aspx page:
TryCast(ContentPlaceHolder1.FindControl("LiteralOnParentASPXPage"), Literal).Text = "some text"
This is a brute force method, but it works when the control is buried deeply in the hierarch of controls:
private Control GetTextEditor(ControlCollection controls)
{
foreach (Control ctrl in controls)
{
if (ctrl.ID != null && ctrl.ID == "teMessage")
return ctrl;
if (ctrl.Controls.Count > 0)
{
Control inner = GetTextEditor(ctrl.Controls);
if (inner != null)
return inner;
}
}
return null;
}
To access means enable/disable controls from .ascx in .aspx file, Try this code it is also the solution.
protected void Page_Load(object sender, EventArgs e)
{
Control ct = PEM.FindControl("btnInsert");
Button btn = (Button)ct;
btn.Enabled = false;
}