Finding the Parent of a Control

T

tshad

If we have nested controls, how do we easily find the parent?

I know how to find Child controls - I would do something like:

****************************************************************************************
Sub OnSelectIndexChanged(sender as Object,e as DataListCommandEventArgs)
trace.warn("inside OnSelectIndesChanged")
try
InfoLabel.Visible = False
if e.CommandName = "Select" then
DataList1.SelectedIndex = e.Item.ItemIndex
end if

dim refCode as Label = e.Item.FindControl("lblRefCode")

Dim oRepeater as Repeater =
CType(DataList1.Items(DataList1.SelectedIndex).FindControl("Repeater1"),Repeater)
Dim oDetail as CheckBox =
CType(DataList1.Items(DataList1.SelectedIndex).FindControl("DetailCheck"),CheckBox)
Dim oBut as ImageButton =
CType(DataList1.Items(DataList1.SelectedIndex).FindControl("ExpandButton"),ImageButton)
*******************************************************************************************

But what if I push a button in a child control and need to get to the Parent
control? Is there an easy way to do this?

Thanks,

Tom.
 
K

Kevin Spencer

Control.Parent

--
HTH,
Kevin Spencer
..Net Developer
Microsoft MVP
Neither a follower
nor a lender be.
 
T

tshad

Kevin Spencer said:
Control.Parent

How would I use that to determine the type of control if I were passed
something like:

sub something(s as object, e as DataListCommandEventArgs)

Thanks,

Tom.
 
K

Kevin Spencer

How would I use that to determine the type of control if I were passed
something like:

sub something(s as object, e as DataListCommandEventArgs)

Huh??? Did someone pass a sub to you? Just pass it back.

--
HTH,
Kevin Spencer
..Net Developer
Microsoft MVP
Neither a follower
nor a lender be.
 
K

Kevin Spencer

Okay, it's hard to know what you're saying. It helps to be precise in your
terminology (as well as good practice for coding).

What you described is a signature for an Event Handler. Generally, the Event
Handler is wired up to an object, so it already knows what it's dealing
with. Perhaps you should elaborate.

I can tell you this much: You can find out anything about any object using
Reflection.

--
HTH,
Kevin Spencer
..Net Developer
Microsoft MVP
Neither a follower
nor a lender be.
 
T

tshad

Kevin Spencer said:
Huh??? Did someone pass a sub to you? Just pass it back.

Actually, I might have this wrong. I am using an EventArgs not the
DataListCommandEventArgs (I think).

I have a Repeater object which has a bunch of asp:Labels and asp:Link
buttons. This Repeater object is part of a DataList object. I need to get
to the parent of the Repeater this control is part of.

A LinkButton might look like:

<asp:LinkButton id="Interviews" runat="server" Text='<%#
DataBinder.Eval(Container, "DataItem.Interviews") %>'
onClick="Interviews_Click" />

I then have a routine:
*************************************************************
sub Interviews_Click(src as object, args as EventArgs)

end sub
****************************************************************

I need to get the DataList object that is the parent of the "Interviews"
control. The Interviews control has the detail information I need to get
and my repeater is a summary. I hope I am explaining this right.

Once I get the Datalist control, I can use FindControl to get the object I
am really after (a reference code, for instance).

So I have something like

<asp:DataList \> objects..
<asp:repeater \> objects such as the link button below
<asp:LinkButton \>

I hope that isn't too confusing (it is to me).

Thanks,

Tom.
 
T

tshad

Kevin Spencer said:
Okay, it's hard to know what you're saying. It helps to be precise in your
terminology (as well as good practice for coding).

What you described is a signature for an Event Handler. Generally, the
Event
Handler is wired up to an object, so it already knows what it's dealing
with. Perhaps you should elaborate.

I can tell you this much: You can find out anything about any object using
Reflection.

I agree.

That is what I am learning. I did send a more elaborate explanation of what
I am trying to do. I hope it is a better explanation.

Thanks,

Tom.
 
J

John Saunders

tshad said:
Actually, I might have this wrong. I am using an EventArgs not the
DataListCommandEventArgs (I think).

I have a Repeater object which has a bunch of asp:Labels and asp:Link
buttons. This Repeater object is part of a DataList object. I need to
get to the parent of the Repeater this control is part of.

A LinkButton might look like:

<asp:LinkButton id="Interviews" runat="server" Text='<%#
DataBinder.Eval(Container, "DataItem.Interviews") %>'
onClick="Interviews_Click" />

I then have a routine:
*************************************************************
sub Interviews_Click(src as object, args as EventArgs)

end sub
****************************************************************

I need to get the DataList object that is the parent of the "Interviews"
control. The Interviews control has the detail information I need to get
and my repeater is a summary. I hope I am explaining this right.

Once I get the Datalist control, I can use FindControl to get the object I
am really after (a reference code, for instance).

So I have something like

<asp:DataList \> objects..
<asp:repeater \> objects such as the link button below
<asp:LinkButton \>

I hope that isn't too confusing (it is to me).

Tom, I think I see what you're getting at, and you may be going about it the
wrong way.

First of all, when a LinkButton is clicked inside of a Repeater, DataList or
DataGrid, an ItemCommand event is raised in the Repeater, DataList or
DataGrid. The RepeaterCommandEventArgs passed to that event handler will
supply it with the CommandName and CommandArgument properties which came
from the LinkButton, and in fact, the CommandSource property will return a
reference to the LinkButton itself. You will also get the Item property,
which is a reference to the RepeaterItem this LinkButton is inside of.

Of course, the sender parameter will be a reference to the Repeater object.
If that is inside of the DataList (or, more accurately, inside of a
DataListItem), then you can get to the DataList by:

private void MyRepeater_ItemCommand(object sender, RepeaterCommandEventArgs
e)
{
Repeater rpt = (Repeater) sender;
Control rptParent = rpt.Parent;
DataList dataList = (DataList) rptParent.Parent; // I think
}


But this only solves half of your problem. The question is exactly what do
you plan to get from that DataList? It sounds like you plan to access the
data to which the list was bound, but it won't be there on a PostBack.

Is this a generic scenario, or something that just happens on a single page?

John Saunders
 
T

tshad

Ok. I almost have what I want. Is there a way of doing this in one
statement?

I need to go up the tree to the DataListItem. The first parent gives me a
RepeaterItem. The second gives me a Repeater and the third gives me the
DataListItem.

The code looks like:

dim theParent as Control = src.Parent
dim theParent2 as Control = theParent.Parent
dim theParent3 as Control = theParent2.Parent
dim theDataList as DataListItem
theDataList = Ctype(theParent3,DataListItem)
dim theLabel as Label = CType(theDataList.FindControl("lblJobTitle"),label)
trace.warn("theLabel = " & theLabel.text)

Is there an easier method to do this? I'd like to do the first 3 lines as
one (since in this case I know it will always take 3 to get to the item I
want).

Thanks,

Tom
 
T

tshad

John Saunders said:
Tom, I think I see what you're getting at, and you may be going about it
the wrong way.

First of all, when a LinkButton is clicked inside of a Repeater, DataList
or DataGrid, an ItemCommand event is raised in the Repeater, DataList or
DataGrid. The RepeaterCommandEventArgs passed to that event handler will
supply it with the CommandName and CommandArgument properties which came
from the LinkButton, and in fact, the CommandSource property will return a
reference to the LinkButton itself. You will also get the Item property,
which is a reference to the RepeaterItem this LinkButton is inside of.

Of course, the sender parameter will be a reference to the Repeater
object. If that is inside of the DataList (or, more accurately, inside of
a DataListItem), then you can get to the DataList by:

private void MyRepeater_ItemCommand(object sender,
RepeaterCommandEventArgs e)
{
Repeater rpt = (Repeater) sender;
Control rptParent = rpt.Parent;
DataList dataList = (DataList) rptParent.Parent; // I think
}

That is similar to what I did, except I went from the object:

dim theParent as Control = sender.Parent
dim theParent2 as Control = theParent.Parent
dim theParent3 as Control = theParent2.Parent
dim theDataList as DataListItem

and then you mentioned to use

dim theParent as Control = sender.Parent.Parent.Parent

which works fine.

I need to look more at your solution, just to understand it better, as it
may be a better way to go now or in the future.
But this only solves half of your problem. The question is exactly what do
you plan to get from that DataList? It sounds like you plan to access the
data to which the list was bound, but it won't be there on a PostBack.
What I am doing is getting a reference code that is on the datalist row.
It is in a label control and seems to be there at the Postback, as it seems
to work fine.

Here is the code I am using:

theParent3 = src.Parent.Parent.Parent
dim theDataList as DataListItem
theDataList = Ctype(theParent3,DataListItem)
dim refCode as Label = CType(theDataList.FindControl("lblRefCode"),label)

I then use the refCode.text in my Sql Statement to get my detail.
Is this a generic scenario, or something that just happens on a single
page?
Just on a single page

The sender.Parent.Parent.Parent works because I know what the structure is
(datalist/repeater/linkbutton) - this obviously would not work for a generic
page.

Thanks,

Tom
 
K

Kevin Spencer

That worked great.
Not sure why, however.

It might be good to know why, for future reference. The Parent property of a
Control is a Control. Every Control has a Parent property. So, if you
reference Parent of a Control, that returns a Control, which also has a
Parent, etc.

You can do the same with functions that return a value. Let's say you have a
function that returns a Control:

public Control ThisFunction()
{
...
}

You could, for example, refer to the Parent of the Control returned by that
Function:

Control c = ThisFunction().Parent;

--
HTH,
Kevin Spencer
..Net Developer
Microsoft MVP
Neither a follower
nor a lender be.
 
T

tshad

Kevin Spencer said:
It might be good to know why, for future reference. The Parent property of
a
Control is a Control. Every Control has a Parent property. So, if you
reference Parent of a Control, that returns a Control, which also has a
Parent, etc.

You can do the same with functions that return a value. Let's say you have
a
function that returns a Control:

public Control ThisFunction()
{
...
}

You could, for example, refer to the Parent of the Control returned by
that
Function:

That does make sense - I just need to think it through.

This is where I get confused. If you have a control and want to get a
specific piece of data from it, you have to convert it first. Take for
example:

theParent3 = src.Parent.Parent.Parent
dim theDataList as DataListItem
theDataList = Ctype(theParent3,DataListItem)
dim refCode as Label = CType(theDataList.FindControl("lblRefCode"),label)

I have a control - theParent3 - that I have to convert to a DataList, before
I can find the label which is a control connected to the DataList (or at
least that is what I was told). Maybe there is a shortcut.

I thought I would have to do the same in the Parent scenario. But since we
are always dealing with controls, I guess that isn't the case.

Thanks,

Tom.
 
J

John Saunders

tshad said:
"John Saunders" <johnwsaundersiii at hotmail.com> wrote in message

Just on a single page

The sender.Parent.Parent.Parent works because I know what the structure is
(datalist/repeater/linkbutton) - this obviously would not work for a
generic page.

But if it's only a single page, then don't you know the name of the
DataList? More importantly, don't you already know the source of the data in
the data list? Just access it directly!

John Saunders
 
J

John Saunders

tshad said:
That does make sense - I just need to think it through.

This is where I get confused. If you have a control and want to get a
specific piece of data from it, you have to convert it first.

No. You don't have to convert it. You have to change the type.

Unlike VB6, VB.NET is strongly-typed. For instance, in:

Dim theParent3 As Control = src.Parent.Parent.Parent

You cannot access theParent3.ItemIndex. That's not because the DataListItem
referenced by theParent3 doesn't have an ItemIndex property. It's because
the Control type doesn't have an ItemIndex property, and because theParent3
is of type "Control". VB6 might let you get away with accessing ItemIndex
directly, performing the type cast behind your back.

Take for example:

theParent3 = src.Parent.Parent.Parent
dim theDataList as DataListItem
theDataList = Ctype(theParent3,DataListItem)

Ok, stop. Do not use CType in this case. Use DirectCast. This is not a
conversion, it's a type cast. A conversion is what happens when you convert
an integer into a double. But in this case, you're not going to change
theParent3 at all - you're just going to reference it as a different type.
dim refCode as Label = CType(theDataList.FindControl("lblRefCode"),label)

Also, you didn't have to do the CType in order to do FindControl to find the
label. Try it with theParent3.FindControl.

Oh, and lose the CType and replace it with DirectCast.


John Saunders
 
T

tshad

John Saunders said:
But if it's only a single page, then don't you know the name of the
DataList? More importantly, don't you already know the source of the data
in the data list? Just access it directly!

I can't.

There are multiple rows in the datalist. I need the row that houses the
repeater. Each datalist row has a repeater which is data relating to that
row. Each datalist row has a key that I use to populate the repeater. So
when I need the key, I need to go up the chain to get to the parent datalist
row to get the key.

Tom.
 
T

tshad

John Saunders said:
No. You don't have to convert it. You have to change the type.

Unlike VB6, VB.NET is strongly-typed. For instance, in:

Dim theParent3 As Control = src.Parent.Parent.Parent

You cannot access theParent3.ItemIndex. That's not because the
DataListItem referenced by theParent3 doesn't have an ItemIndex property.
It's because the Control type doesn't have an ItemIndex property, and
because theParent3 is of type "Control". VB6 might let you get away with
accessing ItemIndex directly, performing the type cast behind your back.



Ok, stop. Do not use CType in this case. Use DirectCast. This is not a
conversion, it's a type cast. A conversion is what happens when you
convert an integer into a double. But in this case, you're not going to
change theParent3 at all - you're just going to reference it as a
different type.


Also, you didn't have to do the CType in order to do FindControl to find
the label. Try it with theParent3.FindControl.

Oh, and lose the CType and replace it with DirectCast.

How would my example look with DirectCast - I am not sure what you mean by
DirectCast. Is it like C when you do a (int)j = 5;

Thanks,

Tom.
 
J

John Saunders

tshad said:
How would my example look with DirectCast - I am not sure what you mean by
DirectCast. Is it like C when you do a (int)j = 5;

dim refCode as Label =
DirectCast(theDataList.FindControl("lblRefCode"),label)


John Saunders
 
J

John Saunders

tshad said:
I can't.

There are multiple rows in the datalist. I need the row that houses the
repeater. Each datalist row has a repeater which is data relating to that
row. Each datalist row has a key that I use to populate the repeater. So
when I need the key, I need to go up the chain to get to the parent
datalist row to get the key.

The DataList has a DataKeys collection, indexed by ItemIndex. Once you get
up to the DataListItem, you can get its ItemIndex and use it to index into
the DataKeys collection of the DataList.

John Saunders
 

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,733
Messages
2,569,440
Members
44,830
Latest member
ZADIva7383

Latest Threads

Top