473,405 Members | 2,171 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

ControlsCollection

Hi,

I've observed some weirdness with the ControlsCollection - do people
think this behaviour makes sense?

I populate a list, comprised of list-items which are user controls at
run time - because they are not tracked by the viewstate I manually "cache"
the controls collection of the list form to session memory at PreRender
thus:

viewstate("Controls") = New Guid().NewGuid().ToString
Session(viewstate("Controls")) = pnlResults.Controls

Now on page_load - i get them back with this:

Dim ControlCollectionID As String
ControlCollectionID = viewstate("Controls")
If Not Session(ControlCollectionID) Is Nothing Then
Dim controls As ControlCollection
controls = Session(ControlCollectionID)
For Each currentCtl As Control In controls
If TypeOf (currentCtl) Is UserControl Then
'write a routine to load the user control in here - first make a
duplicate copy
Dim Cuser As UserControl
Cuser = currentCtl
pnlResults.Controls.Add(Cuser)
Else
'if it isn't a user control then just add it in here as normal
Me.pnlResults.Controls.Add(currentCtl)
End If

Now when I do this you'd expect the CurrentCtl.Controls reference to now
point to the panel's controls collection *not* to the controls collection in
session memory. This is does. However it *also* removes the reference from
the session controls collection to CurrentCtl - the result - the for each
fails to add the last control in the collection (the count is reduced by one
as the reference to CurrentCtl is removed). Does this seem more than a
little bit weird to anyone else? Can anyone explain why it should do this?

Thanks

Nick


Nov 19 '05 #1
5 1261
There are many problems in the code snippet you provided.

First, you don't need to generate a GUID and persist it to the view state to
get the user-specific control collection because, unlike the
HttpApplicationState object, the HttpSessionState object (Session) is unique
for each request. So when you say Session("something"), it's gonna retrieve
whatever has been stored in the key "Something" for the same unique user in a
pervious request. In other words, if you have a hundred concurrent threads
referencing the Session object, each has its own unique, per-user copy of it,
and using the same key ("Something") doesn't matter.

Second, the code is adding the controls from ControlCollection stored in the
session object to the pnlResults whether they're of type UserControl or not.
That's because you're not really making a duplicate (or a clone) of the
control in your code. You're just defining a reference of type UserControl
and making it point to the same object. So in both the if- and else- part,
you're basically adding the same control, albeit through another reference in
the if- part.

I'm not sure what the business scenario you're trying to implement, but it
doesn't seem like the right way to do it. Dynamic controls are meant to be
recreated depending on contextual data in each request. You don't really need
to cache them.


"Nick Stansbury" wrote:
Hi,

I've observed some weirdness with the ControlsCollection - do people
think this behaviour makes sense?

I populate a list, comprised of list-items which are user controls at
run time - because they are not tracked by the viewstate I manually "cache"
the controls collection of the list form to session memory at PreRender
thus:

viewstate("Controls") = New Guid().NewGuid().ToString
Session(viewstate("Controls")) = pnlResults.Controls

Now on page_load - i get them back with this:

Dim ControlCollectionID As String
ControlCollectionID = viewstate("Controls")
If Not Session(ControlCollectionID) Is Nothing Then
Dim controls As ControlCollection
controls = Session(ControlCollectionID)
For Each currentCtl As Control In controls
If TypeOf (currentCtl) Is UserControl Then
'write a routine to load the user control in here - first make a
duplicate copy
Dim Cuser As UserControl
Cuser = currentCtl
pnlResults.Controls.Add(Cuser)
Else
'if it isn't a user control then just add it in here as normal
Me.pnlResults.Controls.Add(currentCtl)
End If

Now when I do this you'd expect the CurrentCtl.Controls reference to now
point to the panel's controls collection *not* to the controls collection in
session memory. This is does. However it *also* removes the reference from
the session controls collection to CurrentCtl - the result - the for each
fails to add the last control in the collection (the count is reduced by one
as the reference to CurrentCtl is removed). Does this seem more than a
little bit weird to anyone else? Can anyone explain why it should do this?

Thanks

Nick


Nov 19 '05 #2
I looked further into your code. When you wire events in the ASPX page
through OnClick="EvenHandler", you need to either define the event handler
Button_Click in the <script runat=server> section of the ASPX page with
private accessibility or define it as protected in the Code Behind class.
That's because the ASPX page becomes a derived class from the Code Behind
class, and it won't be able to see the Code Behind's private members.
"Nick Stansbury" wrote:
Hi,

I've observed some weirdness with the ControlsCollection - do people
think this behaviour makes sense?

I populate a list, comprised of list-items which are user controls at
run time - because they are not tracked by the viewstate I manually "cache"
the controls collection of the list form to session memory at PreRender
thus:

viewstate("Controls") = New Guid().NewGuid().ToString
Session(viewstate("Controls")) = pnlResults.Controls

Now on page_load - i get them back with this:

Dim ControlCollectionID As String
ControlCollectionID = viewstate("Controls")
If Not Session(ControlCollectionID) Is Nothing Then
Dim controls As ControlCollection
controls = Session(ControlCollectionID)
For Each currentCtl As Control In controls
If TypeOf (currentCtl) Is UserControl Then
'write a routine to load the user control in here - first make a
duplicate copy
Dim Cuser As UserControl
Cuser = currentCtl
pnlResults.Controls.Add(Cuser)
Else
'if it isn't a user control then just add it in here as normal
Me.pnlResults.Controls.Add(currentCtl)
End If

Now when I do this you'd expect the CurrentCtl.Controls reference to now
point to the panel's controls collection *not* to the controls collection in
session memory. This is does. However it *also* removes the reference from
the session controls collection to CurrentCtl - the result - the for each
fails to add the last control in the collection (the count is reduced by one
as the reference to CurrentCtl is removed). Does this seem more than a
little bit weird to anyone else? Can anyone explain why it should do this?

Thanks

Nick


Nov 19 '05 #3
Sorry, this reply was meant to another message.

"Homam" wrote:
I looked further into your code. When you wire events in the ASPX page
through OnClick="EvenHandler", you need to either define the event handler
Button_Click in the <script runat=server> section of the ASPX page with
private accessibility or define it as protected in the Code Behind class.
That's because the ASPX page becomes a derived class from the Code Behind
class, and it won't be able to see the Code Behind's private members.
"Nick Stansbury" wrote:
Hi,

I've observed some weirdness with the ControlsCollection - do people
think this behaviour makes sense?

I populate a list, comprised of list-items which are user controls at
run time - because they are not tracked by the viewstate I manually "cache"
the controls collection of the list form to session memory at PreRender
thus:

viewstate("Controls") = New Guid().NewGuid().ToString
Session(viewstate("Controls")) = pnlResults.Controls

Now on page_load - i get them back with this:

Dim ControlCollectionID As String
ControlCollectionID = viewstate("Controls")
If Not Session(ControlCollectionID) Is Nothing Then
Dim controls As ControlCollection
controls = Session(ControlCollectionID)
For Each currentCtl As Control In controls
If TypeOf (currentCtl) Is UserControl Then
'write a routine to load the user control in here - first make a
duplicate copy
Dim Cuser As UserControl
Cuser = currentCtl
pnlResults.Controls.Add(Cuser)
Else
'if it isn't a user control then just add it in here as normal
Me.pnlResults.Controls.Add(currentCtl)
End If

Now when I do this you'd expect the CurrentCtl.Controls reference to now
point to the panel's controls collection *not* to the controls collection in
session memory. This is does. However it *also* removes the reference from
the session controls collection to CurrentCtl - the result - the for each
fails to add the last control in the collection (the count is reduced by one
as the reference to CurrentCtl is removed). Does this seem more than a
little bit weird to anyone else? Can anyone explain why it should do this?

Thanks

Nick


Nov 19 '05 #4
Homann,
First, you don't need to generate a GUID and persist it to the view state to get the user-specific control collection because, unlike the
HttpApplicationState object, the HttpSessionState object (Session) is unique for each request. So when you say Session("something"), it's gonna retrieve whatever has been stored in the key "Something" for the same unique user in a pervious request. In other words, if you have a hundred concurrent threads
referencing the Session object, each has its own unique, per-user copy of it, and using the same key ("Something") doesn't matter.
I understand what you are saying - but i think you've misunderstood
the point of attaching the
GUID to the viewstate - it means that a) i don't have to worry about using
this logic on multiple web forms - because I know that on each
webform the GUID to reference the control collection is different, and B) I
can have many copies of the same form open inside a single session
and not have cross references to the same controls collection
Second, the code is adding the controls from ControlCollection stored in the session object to the pnlResults whether they're of type UserControl or not. That's because you're not really making a duplicate (or a clone) of the
control in your code. You're just defining a reference of type UserControl
and making it point to the same object. So in both the if- and else- part,
you're basically adding the same control, albeit through another reference in the if- part.


That was the general idea - when the webform dies references to each
control should be persisted - so that I can simply add them back in the
second time
around - rather than pulling the data back in from the database etc. I do
know that I am simply adding the same object via the IF / else / end if
statement - it just wasn't working if I didn't cast it to a user control
explicitly like that. I don't know why....

The point I was really asking about was - why does the behaviour in terms of
the user controls / controls collection exist - why does adding a control to
one collection remove it from the other? It just doesn't seem to make sense
to me
Nov 19 '05 #5
If you want to cache the controls per form for each user, you can just
generate the GUID once and reuse it for all requests to this particular form
(i.e. one GUID per form), or even better, just use the form's name as the key
to the Session. As it stands, there's a memory leak because you're not
cleaning up the Session reference of the previous GUID.

If you're simply caching the same controls and adding them to the panel on
each post, then there's no point in generating a new GUID for each request
and re-populating the sesssion object with these controls in the PreRender
event for each request.

What you're essentially doing here is shuffling the same controls back and
forth to the session in each request:

Load:
Panel Controls = Session Controls

PreRender:
Session Controls = Panel Controls

I guess what you need to do is cache the controls once in the session and
don't touch it again on subsequent requests. That's why a single GUID (or any
ID) per form is adequate. In other words, you need to discard the code in the
PreRender event and move the session caching code to the same function that
retrieves the information from the DB.

I'm not sure why you need any casting to assign a Control (supertype)
variable to UserControl (subtype) object. It shouild work without any casting.

"Nick Stansbury" wrote:
Homann,
First, you don't need to generate a GUID and persist it to the view state

to
get the user-specific control collection because, unlike the
HttpApplicationState object, the HttpSessionState object (Session) is

unique
for each request. So when you say Session("something"), it's gonna

retrieve
whatever has been stored in the key "Something" for the same unique user

in a
pervious request. In other words, if you have a hundred concurrent threads
referencing the Session object, each has its own unique, per-user copy of

it,
and using the same key ("Something") doesn't matter.


I understand what you are saying - but i think you've misunderstood
the point of attaching the
GUID to the viewstate - it means that a) i don't have to worry about using
this logic on multiple web forms - because I know that on each
webform the GUID to reference the control collection is different, and B) I
can have many copies of the same form open inside a single session
and not have cross references to the same controls collection
Second, the code is adding the controls from ControlCollection stored in

the
session object to the pnlResults whether they're of type UserControl or

not.
That's because you're not really making a duplicate (or a clone) of the
control in your code. You're just defining a reference of type UserControl
and making it point to the same object. So in both the if- and else- part,
you're basically adding the same control, albeit through another reference

in
the if- part.


That was the general idea - when the webform dies references to each
control should be persisted - so that I can simply add them back in the
second time
around - rather than pulling the data back in from the database etc. I do
know that I am simply adding the same object via the IF / else / end if
statement - it just wasn't working if I didn't cast it to a user control
explicitly like that. I don't know why....

The point I was really asking about was - why does the behaviour in terms of
the user controls / controls collection exist - why does adding a control to
one collection remove it from the other? It just doesn't seem to make sense
to me

Nov 19 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: JohnnyB via DotNetMonster.com | last post by:
Hello, I dont know, if this has already been asked before, I'm sorry if so. VisualBasic: My problem (happens with TreeView, not with AxWebBrowser): treeview uses (no matter, if dock = left,...
3
by: Terrance | last post by:
I've built a user control inherited button and I need it to change the enabled property of all the controls on the form except for the labels and buttons. I'd like to use this control on other...
5
by: Verde | last post by:
I'm using a 3rd party component in an ASP.NET 1.1 Web application. The component has a .Click event that can be fired from the client, with an associated event procedure in the code-behind module....
0
by: Sunil Menon | last post by:
Dear All, I would like to access the ViewState Object of all the controls in the page. When I use the ControlsCollection and access the ViewState Object of a Control, I get an error message "You...
4
by: briandh | last post by:
Hi I have a web form, using vb.net code behind, with a combo box populated with a dataset (Name, ID). What I have found, unlike a windows form, is that if I try to pass a value (ID) into the...
0
by: Joachim | last post by:
Hello, I have a problem with dynamical creation of controls on a WebPage. The program works with the VS 2003 envrionment but not with the VS 2005 8.0.50215.44. To demonstrate it, I have make a...
0
by: Michael Maes | last post by:
Hello, I have a BaseForm with (eg) one Timer in the Components'collection & one Button in the Controls'Collection Also there are three Subs: Load, ScanControls & ScanComponents. The BaseForm is...
0
by: Paul | last post by:
I'd like to iterate through the controls on pages within a dll. I can get a page's Controls in a PropertyInfo class but can't extract the ControlsCollection from there. Dim asm As =...
4
by: =?Utf-8?B?TWF0dCBMb3Zl?= | last post by:
If I extend the WebBrowser class like this: public class CustomWebBrowser : System.Windows.Forms.WebBrowser { public string myProperty() { return "myProperty"; } }
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.