all groups > asp.net building controls > july 2004 >
You're in the

asp.net building controls

group:

Naming container


Naming container Jonas Auken
7/28/2004 4:25:09 PM
asp.net building controls: I'm having a problem with a linkbutton which is not assigned a UniqueID with
all the prefixes for some reason.

The linkbutton resides in a UserControl but is used within a custom control;
both controls implement the INamingContainer.

The strangest thing is, when I click this linkbutton on a page, it's event
is caught and all of a sudden it has a name - why? and from where?

the problem is i need the name before the event phase - more specifically in
the page_load phase - to see if the button has been clicked or not.. is
there a solution; or perhaps a workaround? can I force the name upon the
linkbutton (as it appearently is done later in the lifecycle of the page) or
can I somehow string it together myself?

hope any of this makes sense, cause I'm pretty desperate by now!

/jonas

RE: Naming container v-schang NO[at]SPAM online.microsoft.com
7/29/2004 3:55:16 AM
Hi Jonas,

From your description, you're using a LinkButton control nested in another
container control(Usercontrol or custom control) which implement
INamingContainer. And now you found this will make the LinkButton be auto
generate a name attribute and currently you want to get this value so that
you can check whether the linkbutton is clicked(before its click event
handler be called) when th page is posted back ,yes?

As for this problem, here are my suggetions:
1. Generally all the controls which will be rendered as an <Input type=...>
html element will contains a "name" attirbute, this is used to identify
them in the request's Form collection when the page is submit and post
back. And by default, the "name" attribute's value willl be similiar with
the "id"'s value(I means the id render out to the client), you may have a
test and view the page's source at the clientside to verfiy this.

2. As for the controls nested in other container controls which has
implemented INamingContainer inteface, their ClientID(the actual Id be
rendered to client) will be composited by its own id and its parent
container's id. Also, its name attribute is the same(is not the same with
its serverside control id). You can use the "ClientID" property to get its
actual id, but the "name" attribute will be a bit different , because the
split flag are different, for example:
if the id rendered out is
UserControl_LinkButton1, then the name of it will be
UserControl:LinkButton1

3. When the linkbutton is clicked , it'll actually call the __doPostBack()
client script (auto genreated by the asp.net). You can view the page's
source in the clientside to have a look at the "__doPostBack" function's
code , that will tell you how to "name" of the linkbutton is generated on
the fly.
Here is the code i pull from the page source:
============================
function __doPostBack(eventTarget, eventArgument) {
var theform;
if (window.navigator.appName.toLowerCase().indexOf("microsoft") > -1) {
theform = document.Form1;
}
else {
theform = document.forms["Form1"];
}
theform.__EVENTTARGET.value = eventTarget.split("$").join(":");
theform.__EVENTARGUMENT.value = eventArgument;
theform.submit();
}

=============================
Then, in the serverside , we can use the "__EVENTTARGET" argument to get
the linkbutton's "name" which is posted back. It use the
" theform.__EVENTTARGET.value = eventTarget.split("$").join(":");"

to change all the "$" to ":", that's the acutal value you can check in the
Request.Form collecdtion at serverside.

Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)


Re: Naming container Jonas Auken
7/29/2004 10:21:59 AM
hi Steven,

that will definitely work - thank you very much. only small problem is, that
i cannot use the unique name of the linkbutton - only it's id, to see if it
has been clicked - and since i'm bound to run into a situation where this is
relevant, i might as well ask now..

the linkbuttons unique id (as sent to the client) is:
_ctl5:_ctl5:_ctl0:_ctl0:Hint1:lnkText
- i will split this string and compare the last bit with the linkbuttons id
to see if it is indeed this button, which has been clicked - so far so good.

the problem i still have (as far as i can see) actually is that the control
tree is not built properly in before page_load, but for some reason has been
built by the engine by the time events are handled (ie. prerender):
The linkbutton's parent is a class called Target. This object does not have
a parent in page_load - but when we reach prerender it has! This parent is a
control we have made ourselves - and hence it is properly not correct. The
aspx code for using it looks like this:

<%@ Register TagPrefix="cw" Namespace="Csite.Web" Assembly="CsiteWeb" %>
<cw:hint id="Hint1" runat="server">
<cw:Target id="cTarget">
<td>
<asp:imagebutton id="lnkImage" CssClass="soegtab"
Runat="server"></asp:imagebutton>
<asp:linkbutton id="lnkText" CssClass="soegtab"
Runat="server"></asp:linkbutton>
</td>
</cw:Target>
<cw:Source>
<div class="hintClass">
Klik "Din profil" for at vælge<br />denne søgemetode som standard.
</div>
</cw:Source>
</cw:hint>

The Target class has ParseChildren(false) and the following method for
adding children:
protected override void AddParsedSubObject(object obj) {
if (obj is System.Web.UI.Control) {
Controls.Add((Control)obj);
}
}

Is has no CreateChildControls method.

The Hint class has ParseChildren(true,"Settings"), which puts Source and
Target objects into a collection - these are add to Controls in this method:
protected override void CreateChildControls() {
Controls.Clear();
if (SourceTemplate != null) {
Controls.Add(SourceTemplate);
}
if (TargetTemplate != null) {
Controls.Add(TargetTemplate);
}
}

SourceTemplate looks like this:
public Source SourceTemplate{
get {
if (settings != null) {
foreach (HintSetting s in Settings) {
if (s is Source) {
return s as Source;
}
}
}
return null;
}
}

and settings:
[
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
NotifyParentProperty(true),
PersistenceMode(PersistenceMode.InnerDefaultProperty)
]
public HintSettingCollection Settings
{
get
{
if (settings == null)
{
settings = new HintSettingCollection();
if (IsTrackingViewState)
{
((IStateManager)settings).TrackViewState();
}
}
return settings;
}
}

Can you explain why the control tree behaves like this? What are we doing
wrong?

I hope all this code makes things clearer - I must admit I do not see the
full picture ;)
And I hope you can help..

Sincerely,
Jonas Auken


[quoted text, click to view]

Re: Naming container Jonas Auken
7/29/2004 11:00:08 AM
hi Steven,

After writing you the last message, I poked around a bit longer - it seemed
to me, that if I could call CreateChildControls on the Hint object, then the
tree would be build properly.. I just couldn't explain why this was not
already done.. anyway, I called the Databind method in the Hint class which
was overridden as:
public override void DataBind()

{

EnsureChildControls();

base.DataBind();

}

This made everything allright! I'm not completely sure that I know why; but
the fact is, that now the control tree is wellformed (all parents has been
set) and the linkbutton has been assigned the correct unique id..

So, I guess that's good enough for me.

Regards,
Jonas

Re: Naming container v-schang NO[at]SPAM online.microsoft.com
7/30/2004 8:17:11 AM
Hi Jonas,

Thanks for your followup. I'm also very glad that the issue has been
resolved. Anyway, if you encounter any new problems, please always feel
free to post here. Have a good day!

Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
AddThis Social Bookmark Button