views:

1439

answers:

5

I've created some Web User Controls (.ascx files) and dropped them into Pages. The user controls have some TextBoxes in them that I'd like the Page to be able to access directly.

What's the easiest (read: least time) way to expose these TextBoxes in the user controls to the Pages containing the user controls?

The two options I know are calling myUserControl.FindControl(id) from the Pages (does this even work from the Page?), and writing properties in the user controls to expose the TextBox values.

Neither seem ideal. FindControl() requires the Page know the IDs of the TextBoxes in the user controls, thereby breaking encapsulation and adding hard-coded strings, and writing a bunch of properties in the user controls will be very time consuming given the number of TextBoxes in these user controls.

There's no way to declare these TextBoxes in my user controls be public instead of protected?

A: 

Why not give your user control a collection of TextBoxes, expose the collection as a property, and in your Init() method, just add all your textboxes to the collection?

That way, you have a collection that you can search by ID if you ever need to, without relying on any page logic, and you only have to expose one property. If you make your own collection class for it, you could even program in a couple of handy methods for accessing the textboxes the way you need to.

womp
+1  A: 

If I have to do this I will write a public property that exposes the controls. However there is usually a way to rewrite the information such that you don't need to expose the internal controls. If all you need is the value, create a property that returns the value. If you need client ids, perhaps creating a client object that exposes values or events will solve the issue. Remember, once you make it public, you are exposes a contract and changing that contract will almost always be painful.

Daniel
+1  A: 

(Setting aside the obvious comments about the fact that what you're describing is essentially the opposite of best practice...)

If you are using a Web Application type project, you should have a designer.cs file for each UserControl. That contains the declaration of each child control, so you can change the access modifier to public.

If you are using a Web Site type project, you should probably convert to Web Application. According to Microsoft (and backed up by experience), the Web Site type is not intended for use when you plan to write extensive code which spans beyond a single code-behind.

Rex M
A: 

Derive all of your Web User Controls from a common base class and expose this functionality as a public method (or methods). Your base class can derive from UserControl (the way an .ascx normally would) and your controls in turn derive from it.

Then, even if using reflection seems like a bit of work, you're only doing it once. If the textboxes are dynamic and you want to avoid hardcoding things, this would be the way to go.

So, if you need to just get the value of the text box by id from a parent, you can add something like the following to your base class:

    public string GetTextboxValue(string id)
    {
        string textValue = string.Empty;
        Control ctl = FindControl(id);
        if (ctl.GetType() == typeof(TextBox))
            textValue = ((TextBox)ctl).Text;
        return textValue;
    }

I'd say to go this route vs. the previous suggestion of making the TextBox public since you really only want to read the text value from the parent and not expose the entire object as read/write.

Rich
A: 

You can expose it as a property from the code behind. You'll really only be able to access it's properties from code, not from the ASP.Net designer though. This is an example in vb that exposes a DropDownList on a user control (and, it may not be a best practice but it certainly beats writing code to expose every property on the child controls):

''' <summary>
''' This is the exposed DropDownList for this control.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public ReadOnly Property DrowDownList() As DropDownList
    Get
        Return ddControlList
    End Get
End Property
John