简体   繁体   中英

Nested ASCX controls' properties not accessible at Page-level

Note, before marking as duplicate - similar questions have been asked before, but all reference specific third-party libraries with solutions to match. This question relates solely to the native ASP.Net framework, and I am looking for an explanation of why this behaviour occurs in addition to the best solution.

I have a Page structure like this:

在此处输入图片说明

Within ControlA, I expose the textbox as a Public Property so that I can access it at page-level. So, at page-level, this works perfectly:

Trace.Warn(ControlA.TextBoxA.Text) ' prints "Control A Text Box"

However, exposing ControlB's textbox as a public property in the same manner does not allow it to be available at page-level. This code at page-level...

Trace.Warn(ControlA.NestedControlB.TextBoxB.Text)

...fails with this error:

BC30652: Reference required to assembly 'App_Web_3jwc5ppn

The same is also true of any methods that are placed in ControlB that need to be accessible at page-level. Clicking the "Add Reference" link achieves nothing, and moreso, the assembly title changes every time the project is rebuilt.

A solution, but is it the best for complex controls?

I can bubble up the properties by declaring the ControlB textbox as a property in ControlA, like this:

Public ReadOnly Property NestedControlBTextBox As TextBox
    Get
        Return ControlB.TextBoxB()
    End Get
End Property

This allows the nested textbox to be accessible at page-level with this:

Trace.Warn(ControlA.NestedControlBTextBox.Text) ' prints "Control B Text Box"

But is this the best/correct approach? It seems like an awful lot of work to bubble up every property and/or event up N levels of hierarchy. Obviously my real ASCX controls are way more complex than this.

I have enclosed the solution in case anyone wants to illustrate a better approach.

YOUR ERROR: "why this behavior occurs"...

In order to access the property with your current syntax, you need to add the missing reference to the nested control on the parent page. You are only registering ControlA on the parent page, not ControlB. So trying to access the nested control properties the way you are doesn't work because it has access to ControlA, but does not have access to all the references that exist in ControlA ( ie ControlB's properties). Unless you register the nested control on the parent as well, your current syntax will not work. This doesn't seem ideal, and wont be very readable.

YOUR SOLUTION: is it the best solution?

According to THIS Microsoft article, you should solve the problem similarly to how you currently are. Add properties and Methods that return the values you require from the nested control to the parent control(ControlA). This is annoying and can be painful as your controls get more complex, or have multiple layers of nesting.

MY PREFFERED SOLUTION:

Maybe I'm a rebel, but I don't like changing controls just because my "parent page" says so. I don't want to modify a control to access it's nested control values for the parent page every time I need a new value.

To get a nested controls control value (ie the TextBox on the nested Control), I just do:

Dim myTextBoxB = CType(ControlA.FindControl("ControlB").FindControl("txt_controlB"), TextBox)
Trace.Warn(myTextBoxB.Text)

To go a level deeper, you can do:

Dim myTextBoxC = CType(ControlA.FindControl("ControlB").FindControl("ControlC").FindControl("txt_controlC"), TextBox)
Trace.Warn(myTextBoxC.Text)

The whole idea behind user controls is modularity, and simplification. While you are looking for a best practice, make sure to remember that the deeper you go down the nesting rabbit hole, while trying to access values on the nested controls, the more tightly coupled your application will be...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM