Child user control accessing parent properties

M

Michael

We have a user control (Titlebar) that loads other user controls (children)
into itself based on a property set in the HTML:

<fss:Titlebar id="empStmtListing" runat="server"
UserControl="StatementListing.ascx" Width="90"
HelpId="1" ListingType="3"></fss:Titlebar>

Some of the children user controls need properties set to execute. We would
put these properties in the HTML of the parent,
for example, the ListingType property above. Is there anyway that
StatementListing.ascx can access and read the ListingType
property? Or will our Titlebar user control always have to pass the
properties into the child control?

Thanks
 
J

John Saunders

Michael said:
We have a user control (Titlebar) that loads other user controls (children)
into itself based on a property set in the HTML:

<fss:Titlebar id="empStmtListing" runat="server"
UserControl="StatementListing.ascx" Width="90"
HelpId="1" ListingType="3"></fss:Titlebar>

Some of the children user controls need properties set to execute. We would
put these properties in the HTML of the parent,
for example, the ListingType property above. Is there anyway that
StatementListing.ascx can access and read the ListingType
property? Or will our Titlebar user control always have to pass the
properties into the child control?

It's really bad form for a child control to know too much about its parent.
Instead, let the parent tell the child what it needs to know.
 
X

XicoLoKo

Another approach would be to have a base usercontrol class, lets say TitleBarChildControlBase, that exposes those properties from it's parent.

User controls that inherit TitleBarChildControlBase would be used only inside the TitleBar.

- xicoloko -
 
J

John Saunders

XicoLoKo said:
Another approach would be to have a base usercontrol class, lets say
TitleBarChildControlBase, that exposes those properties from it's parent.
User controls that inherit TitleBarChildControlBase would be used only
inside the TitleBar.

Ok, I originally read the OP as asking a question about user controls in
general. If, instead, the user controls in question will _always_ be used
inside of the same parent control, then knowing about their parent would be
ok.

In this case, it would be ok if the user controls were to cast their Parent
property to the type of the parent:

VB.NET:

Dim tbParentTitlebar As Titlebar = DirectCast(Parent, GetType(Titlebar))
' Can now use tbParentTitlebar.ListingType

C#:

Titlebar tbParentTitlebar = (Titlebar) Parent;
// Can now use tbParentTitlebar.ListingType
 
D

Donald Welker

Sorry, that should be Parent.aspx where it says Parent.ascx; I've already realized this won't work because (Sub)Control.ascx's parent is a Panel (not shown), but you get the idea -- what's the "right" way?
 
D

Donald Welker

Sorry, that should be Parent.aspx where it says Parent.ascx; I've already realized this won't work because (Sub)Control.ascx's parent is a Panel (not shown), but you get the idea -- what's the "right" way?
 
J

John Saunders

Donald Welker said:
I have a parent web page that has dynamic child controls, some of which
are nested. I would like for all of the child controls to have access to
the parent's service objects so they can use the same database connection
etc.
Since it is possible for a control to be instantiated from either the
parent page directly or from a control on the parent page, is it possible/OK
for me to cast the parent Page to a Control in order to access the shared
object(s)?
Summarized example: Suppose Parent.aspx loads and displays
SubControl.ascx either directly in a panel, or as a component of
Control.ascx instead. In Parent.ascx I write:
...
Friend Log as LogOps ' routines to access the log
...
Then in both Control.ascx and SubControl.ascx I write:
...
Dim Mom as Control = DirectCast(Parent,Control)
Dim Log as LogOps = Mom.Log
...
or do I have to somehow determine whether the parent is a page or a
control?

Donald,

My first suggestion would be to set "Options Strict" on. You may find it
enlightening.

Second, I recommend that the parent should pass to the child anything which
is owned by the parent but required by the child. In your case, I would add
a Log property to the child controls and I'd let the parent set that
property after it instantiates the child controls. Presumably, your "Log"
object is pretty much read-only? I wouldn't want multiple child controls
changing it in an unpredictable sequence.

BTW, I wouldn't worry about sharing database connections at all. The
connections will likely be pooled, so a second, "duplicate" connection
shouldn't use many additional resources. Also, it doesn't seem right for a
child control to be using the parent's connection, in effect taking it over
from the parent. The child could then do things "behind the parent's back",
which is not a good idea.
 
D

Donald Welker

The log object in this case is a set of shim routines to write to the NT event log, so it's not much of a risk at the moment. I'm writing a "wizard" to help build a complex document and have broken up sections into about a dozen web controls, each with it's own edit and display panel. When the user is done the final document is recorded in a database and presented for printing, so each control is supposed to be smart enough to edit its portion of the draft document and display its fields in the final version. My original thought was to write one module to communicate with the database and share it throughout, but it occurs to me that the controls will have different data adapters and don't need access to each others' data -- but I need to make sure the connection string is shared.

What I've now done is created a "template" control from which to derive the others, but now the derived controls won't load in the designer: "Abstract Class" -- do I need to add a reference to the template or can I no longer use the designer?
 
J

John Saunders

Donald Welker said:
The log object in this case is a set of shim routines to write to the NT
event log, so it's not much of a risk at the moment. I'm writing a "wizard"
to help build a complex document and have broken up sections into about a
dozen web controls, each with it's own edit and display panel. When the
user is done the final document is recorded in a database and presented for
printing, so each control is supposed to be smart enough to edit its portion
of the draft document and display its fields in the final version. My
original thought was to write one module to communicate with the database
and share it throughout, but it occurs to me that the controls will have
different data adapters and don't need access to each others' data -- but I
need to make sure the connection string is shared.
What I've now done is created a "template" control from which to derive
the others, but now the derived controls won't load in the designer:
"Abstract Class" -- do I need to add a reference to the template or can I no
longer use the designer?

As to the connection and/or connection string, you could pass that into the
controls. Just add a Connection property of type SqlConnection (or whichever
connection type you need).

As to the "no inherited user controls" problem - that's just another
trade-off with user controls. The designer isn't clever enough to do what
you want there. If you used custom controls, you wouldn't have this problem,
but you _would_ take longer to get the project done. You can have your user
controls all inherit from a base class, but that base class can't do
anything as far as UI goes. I've done this successfully in the past.

Good Luck,
John Saunders
johnwsaundersiii at hotmail
 
J

John Saunders

Donald Welker said:
What I have now are a dozen controls that are different classes. What I'd
like to do is set all their properties at the same time. It would be really
nice to treat them as an array or collection and loop through each of them
to set the same properties. I guess I could use the New method as an
alternative.


Donald,

If they all inherit from the same base class, then there should be no
problem in setting all their properties at the same time. In fact, you would
be able to use Reflection to find all of those controls and set their
properties at once.

Now, a different (and perhaps better) solution just struck me. Since all of
the controls will require access to the same values of the same set of
properties, it makes sense to encapsulate all of those properties in a
single class. The parent page could then create a single instance of this
class and set the properties of this single instance. Then, each control can
be passed a reference to this single instance. For example (not tested):

Public Class ControlProperties
Public Property ConnectionString As String
...
End Property
'
Public Property Log As LogOps
...
End Property
...
End Class
'
Public Class MyControlBaseType
Inherits UserControl

Public Property Properties As ControlProperties
...
End Property
End Class

' In the page:
Protected Sub Page_Load (sender As Object, e As EventArgs)
...
Dim props As ControlProperties = New ControlProperties()
props.ConnectionString = "..."
props.Log = Log ' Or whatever
'
SetCommonProperties(props, Me.Controls)
End Sub

Private Sub SetCommonProperties(props As ControlProperties, ctls As
ControlCollection)
For Each ctl As Control In ctls
If TypeOf ctl Is MyControlBaseType Then
Dim base As MyControlBaseType = DirectCast(ctl,
MyControlBaseType)
base.Properties = props
End If
'
If ctl.HasControls Then
SetCommonProperties(props, ctl.Controls)
End If
Next
End Sub

You could also choose to avoid the common base type by getting fancy with
Reflection. Instead of checking to see if the control is a
MyControlBaseType, you could check to see if it had a property named
"Properties" which was of a type which derived from "ControlProperties". You
would have to use Reflection to set the value of that property, however.

I hope that helps.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top