Here's what I'm doing: I am dynamically creating a large table with quite
a few embedded controls. I've added eventhandlers for the dynamic controls
and the events all fire correctly because I've recreated the table and
controls on postback. So far, so good......
Now, the result of the events in the dynamic table controls are to re-create
the same table and controls that are raising the events. If I "re-create"
the table in the postback events I get another instance of my table (now I
have two tables on the page). I've done a response.redirect to the page
which gives me the correct result...but this seems inefficient.
So back to my question and the paradox: On a postback, how would I replace
the table (or any other control) which I had to recreate on the postback in
order to have the events fire.
I'm using VB.NET and I've create my table and controls all within a web user
control.
Thanks
Brad
I don't understand your comment about having add the controls in a post
back. Here's a sample in which the dynamically added controls are added
from the first browsing of the page.
Protected WithEvents TextBox1 As System.Web.UI.WebControls.TextBox
Protected WithEvents Button1 As System.Web.UI.WebControls.Button
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
TextBox1 = New TextBox()
Button1 = New Button()
Me.Controls(1).Controls.Add(TextBox1)
Me.Controls(1).Controls.Add(Button1)
End Sub
Private Sub TextBox1_TextChanged(ByVal sender As Object, ByVal e As
System.EventArgs) Handles TextBox1.TextChanged
Response.Write(TextBox1.Text)
End Sub
Private Sub Button1_Click(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Button1.Click
Button1.Text = TextBox1.Text
End Sub
Can you post a sample which demonstrates what you are doing?
If you can, create a sample with just one or two controls and no table or
user control. If that's too simplistic to demonstrate the behavior, try to
create a sample that's as simple as possible that does demonstrate the
behavior.
Thank you, Mike Moore
Microsoft, ASP.NET
This posting is provided "AS IS", with no warranties, and confers no rights.
--------------------
>Reply-To: "Brad" <nos...@co.lane.or.us>
>From: "Brad" <nos...@co.lane.or.us>
>Subject: Dynamic Controls - how to replace after their events fire
>Date: Fri, 11 Oct 2002 10:42:15 -0700
>Lines: 28
>X-Priority: 3
>X-MSMail-Priority: Normal
>X-Newsreader: Microsoft Outlook Express 6.00.2600.0000
>X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000
>Message-ID: <eKR#e1UcCHA.2052@tkmsftngp12>
>Newsgroups: microsoft.public.dotnet.framework.aspnet.webcontrols
>NNTP-Posting-Host: 199.79.46.126
>Path: cpmsftngxa08!tkmsftngp01!tkmsftngp12
>Xref: cpmsftngxa08
microsoft.public.dotnet.framework.aspnet.webcontrols:6318
>X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.webcontrols
Here's where I hope I remain clear....
**IF** I understand correctly, .Net has to re-render the table and it's
controls on the post back before any events fire for controls that were
rendered within the table. So, the re-rendering takes place *before* my
Change event is fired. My expected result is that the Change event will
move the calendar forward/back a week, to the week currently stored in the
session variable "eventdate".
(1) If I do nothing, the page does move forward/back but it is always one
week out of sync with the expected date. This out of sync makes sense as
the controls were re-rendered before the event is fired that updates the
session variable "eventdate".
(2) If I use a response.redirect back to the same page everything work fine
because the first instance of the page updates the date and redirects to
itself, where the page/control is drawn with the updated date.
(3) If attempt to re-render the table and controls in the Change event I
two instances of the table drawn on the page #1 prior to the event being
fired and #2 after the event was fired.
In conclusion, using (2) the redirect, gives me the result I expected and I
could keep quite and go away.......but I was wondering if there was a better
way to do this...without having to do a redirect?
Thanks
Brad
'********************************************************
' Start of my example. This entire code sample can be cut/pasted into a
user web control
' (there may be some word wraps from any email formatting)
'********************************************************
Public MustInherit Class MyControl
Inherits System.Web.UI.UserControl
#Region " Web Form Designer Generated Code "
'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
End Sub
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
BuildDisplay()
InitializeComponent()
End Sub
#End Region
Private Property EventDate() As Date
Get
If Not (IsNothing(Session("eventdate"))) Then
Return Session("eventdate")
Else
Return Today
End If
End Get
Set(ByVal Value As Date)
Session("eventdate") = Value
End Set
End Property
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
End Sub
Private Function BuildDisplay()
Dim tblWeek As New Table()
Dim tblr As TableRow
Dim tblc As TableCell
Dim intHour As Integer
Dim intDay As Integer
Dim dteDisplay As Date
If EventDate.DayOfWeek <> DayOfWeek.Sunday Then
dteDisplay = DateAdd(DateInterval.Day, EventDate.DayOfWeek * -1,
EventDate)
End If
With tblWeek
.ID = "tblWeek"
.Width = New Unit(100, UnitType.Percentage)
.CellPadding = 0
.CellSpacing = 0
.BorderStyle = BorderStyle.Solid
.BorderWidth = New Unit(1, UnitType.Pixel)
End With
'********************************************
' Build Title
'********************************************
tblr = New TableRow()
With tblr
tblc = New TableCell()
Dim lbtn As New LinkButton()
lbtn.CommandName = DateInterval.Day
lbtn.CommandArgument = -7
lbtn.Text = "<<"
lbtn.ToolTip = "Previous Week"
AddHandler lbtn.Click, AddressOf Me.Change
tblc.Controls.Add(lbtn)
tblr.Cells.Add(tblc)
End With
With tblr
tblc = New TableCell()
tblc.Text = "Week of " & Format(dteDisplay, "MMMM d, yyyy")
tblc.ColumnSpan = 7
tblr.Cells.Add(tblc)
End With
With tblr
tblc = New TableCell()
Dim lbtn As New LinkButton()
lbtn.CommandName = DateInterval.Day
lbtn.CommandArgument = 7
lbtn.text = ">>"
lbtn.ToolTip = "Next Week"
AddHandler lbtn.Click, AddressOf Me.Change
tblc.Controls.Add(lbtn)
tblr.Cells.Add(tblc)
End With
tblWeek.Rows.Add(tblr)
'********************************************
' Build Day Titles
'********************************************
tblr = New TableRow()
With tblr
tblc = New TableCell()
tblc.Wrap = False
.Cells.Add(tblc)
End With
Dim dteTitle As Date = dteDisplay
For intDay = DayOfWeek.Sunday To DayOfWeek.Saturday
tblc = New TableCell()
tblc.Text = Format(dteTitle, "ddd, MMM d")
tblc.BorderStyle = BorderStyle.Solid
tblc.BorderWidth = New Unit(1, UnitType.Pixel)
tblr.Cells.Add(tblc)
dteTitle = DateAdd(DateInterval.Day, 1, dteTitle)
Next
With tblr
tblc = New TableCell()
tblc.Wrap = False
.Cells.Add(tblc)
End With
tblWeek.Rows.Add(tblr)
'********************************************
' Build Time and Days
'********************************************
For intHour = 7 To 19
tblr = New TableRow()
Dim strTime As String = Format(DateAdd(DateInterval.Hour,
intHour, Today()), "hh:mm tt")
With tblr
tblc = New TableCell()
tblc.Wrap = False
tblc.Text = strTime
tblc.BorderStyle = BorderStyle.Solid
tblc.BorderWidth = New Unit(1, UnitType.Pixel)
.Cells.Add(tblc)
End With
For intDay = 0 To 6
tblc = New TableCell()
With tblc
.Text = ""
tblc.BorderStyle = BorderStyle.Solid
tblc.BorderWidth = New Unit(1, UnitType.Pixel)
End With
tblr.Cells.Add(tblc)
Next
With tblr
tblc = New TableCell()
tblc.Wrap = False
tblc.Text = strTime
tblc.BorderStyle = BorderStyle.Solid
tblc.BorderWidth = New Unit(1, UnitType.Pixel)
.Cells.Add(tblc)
End With
tblWeek.Rows.Add(tblr)
Next
Me.Controls.Add(tblWeek)
End Function
Private Sub Change(ByVal sender As System.Object, ByVal e As EventArgs)
EventDate = DateAdd(CType(sender.commandname, DateInterval),
CType(sender.commandargument, Double), EventDate)
Response.Write(EventDate)
' Uncommenting this next line will render a calendar of the correct
week
' however there will be two calendars drawn on the page
'************************
' BuildDisplay()
'
'************************
'Uncommenting this line instead will display the expected
results...because is causes a new page to be
' rendered...and it's using the revised EventDate session
parameter. Note the "" as this expects
' to be used in a page names "default.aspx"
' Response.Redirect("")
End Sub
End Class
'********************************************************
' End of my example
'********************************************************
""Mike Moore [MS]"" <mic...@online.microsoft.com> wrote in message
news:xYJN8e7cCHA.1904@cpmsftngxa06...
I agree, this is a self-defeating situation. .NET won't fire the control's
change event unless a change has occurred on the control. This requires
that you create the control first, before .NET examines whether a change
has occurred. If you don't create the control until later, then .NET won't
recognize the change and won't fire the change event.
Meanwhile, the creation of your control is dependant on the results of the
change event. So, creation of the control must take place before the change
event in order for the change event to fire. Also, the control must be
created after the change event because the results of the change event are
required in order to display the control with the new data.
I've tried several experiments and haven't found a resolution yet. I expect
to have more for you tomorrow.
Thank you, Mike Moore
Microsoft, ASP.NET
This posting is provided "AS IS", with no warranties, and confers no rights.
--------------------
>Reply-To: "Brad" <nos...@co.lane.or.us>
>From: "Brad" <nos...@co.lane.or.us>
>References: <eKR#e1UcCHA.2052@tkmsftngp12> <xYJN8e7cCHA.1904@cpmsftngxa06>
>Subject: Re: Dynamic Controls - how to replace after their events fire
>Date: Mon, 14 Oct 2002 15:02:25 -0700
>Lines: 341
>X-Priority: 3
>X-MSMail-Priority: Normal
>X-Newsreader: Microsoft Outlook Express 6.00.2600.0000
>X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000
>Message-ID: <OrvI208cCHA.1652@tkmsftngp09>
>Newsgroups: microsoft.public.dotnet.framework.aspnet.webcontrols
>NNTP-Posting-Host: 199.79.46.126
>Path: cpmsftngxa06!tkmsftngp01!tkmsftngp09
>Xref: cpmsftngxa06
microsoft.public.dotnet.framework.aspnet.webcontrols:6327
>X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.webcontrols
I have also used redirect succesfully, but depending on the control, there
might be a better option that just rebinding the data and do a redirect:
re-instancing the control. Given that the Page_Render-event comes after
control events, the control eventhandler can add or remove new controls.
Thus you might want to make you calender as composite control itself, making
you able to remove and re-instancing it easily.
An example:
Public Class ModulLogout : Inherits Control : Implements INamingContainer
Protected Overrides Sub CreateChildControls()
Dim LogoutButton As New LinkButton
LogoutButton.Text = "Logout"
LogoutButton.Id = "Logout"
LogoutButton.CommandName = "Logout"
AddHandler LogoutButton.Command, AddressOf Logout
Me.Controls.Add(LogoutButton)
End Sub
Private Sub Logout(sender As Object, e As CommandEventArgs)
FormsAuthentication.SignOut()
Me.Controls.Clear
Me.Controls.Add(New LiteralControl("<p>Logged out!</p>")
End Sub
Kim :o)
My solution is a variation on Kim's. I don't clear all the controls, just
the one we're concerned about. I found that I had to make the removal a
recursive function to get all nested child controls.
Here's the previous code sample with a new function added to remove the old
control before re-adding it in the change event.
'********************************************************
' Start of my example. This entire code sample can be cut/pasted into a
user web control
' (there may be some word wraps from any email formatting)
'********************************************************
Imports System.Reflection
Public MustInherit Class MyControl
Inherits System.Web.UI.UserControl
Dim tblWeek As Table
#Region " Web Form Designer Generated Code "
'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
End Sub
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
BuildDisplay()
End Sub
#End Region
Private Property EventDate() As Date
Get
If Not (IsNothing(Session("eventdate"))) Then
Return Session("eventdate")
Else
Return Today
End If
End Get
Set(ByVal Value As Date)
Session("eventdate") = Value
End Set
End Property
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
End Sub
Private Function BuildDisplay()
Dim tblr As TableRow
Dim tblc As TableCell
Dim intHour As Integer
Dim intDay As Integer
Dim dteDisplay As Date
Response.Write(EventDate)
tblWeek = New Table()
If EventDate.DayOfWeek <> DayOfWeek.Sunday Then
dteDisplay = DateAdd(DateInterval.Day, EventDate.DayOfWeek *
-1, EventDate)
End If
With tblWeek
.ID = "tblWeek"
.Width = New Unit(100, UnitType.Percentage)
.CellPadding = 0
.CellSpacing = 0
.BorderStyle = BorderStyle.Solid
.BorderWidth = New Unit(1, UnitType.Pixel)
End With
'********************************************
' Build Title
'********************************************
tblr = New TableRow()
With tblr
tblc = New TableCell()
Dim lbtn As New LinkButton()
lbtn.CommandName = DateInterval.Day
lbtn.CommandArgument = -7
lbtn.Text = "<<"
lbtn.ToolTip = "Previous Week"
lbtn.ID = "LEFT"
AddHandler lbtn.Click, AddressOf Me.Change
tblc.Controls.Add(lbtn)
tblr.Cells.Add(tblc)
End With
With tblr
tblc = New TableCell()
tblc.Text = "Week of " & Format(dteDisplay, "MMMM d, yyyy")
tblc.ColumnSpan = 7
tblr.Cells.Add(tblc)
End With
With tblr
tblc = New TableCell()
Dim lbtn As New LinkButton()
lbtn.CommandName = DateInterval.Day
lbtn.CommandArgument = 7
lbtn.Text = ">>"
lbtn.ToolTip = "Next Week"
lbtn.ID = "RIGHT"
tblWeek.Rows.Add(tblr)
Next
Me.Controls.Add(tblWeek)
End Function
'Remove the existing control including children
'Start from the top level container
RemoveAll(Me)
'Re-add the control, including children
BuildDisplay()
End Sub
'*******************************************************************
'SUB RemoveAll - parameter Control
'Remove all existing controls from the specified control.
'Start from the end of the control collection
'to avoid index out of range errors
'cannot do this with a for each loop, becuase that would modify
'the collection that the enumerator is bound to, which is an error.
'*******************************************************************
Public Sub RemoveAll(ByRef container As Control)
Dim ctl As Control
Dim x As Integer
For x = container.Controls.Count - 1 To 0 Step -1
ctl = container.Controls(x)
If ctl.HasControls Then
'do a recursive remove, we are removing the controls in the
container
'before removing the container
RemoveAll(ctl)
End If
container.Controls.Remove(ctl)
Next
End Sub
End Class
Thank you, Mike Moore
Microsoft, ASP.NET
This posting is provided "AS IS", with no warranties, and confers no rights.
--------------------
>From: "Kim Bach Petersen" <msn...@kensho.dk>
>References: <eKR#e1UcCHA.2052@tkmsftngp12> <xYJN8e7cCHA.1904@cpmsftngxa06>
<OrvI208cCHA.1652@tkmsftngp09>
>Subject: Re: Dynamic Controls - how to replace after their events fire
>Date: Tue, 15 Oct 2002 12:33:54 +0200
>Lines: 32
>X-Priority: 3
>X-MSMail-Priority: Normal
>X-Newsreader: Microsoft Outlook Express 6.00.2720.3000
>X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000
>Message-ID: <OzFYyYDdCHA.392@tkmsftngp09>
>Newsgroups: microsoft.public.dotnet.framework.aspnet.webcontrols
>NNTP-Posting-Host: 80.198.43.82
>Path: cpmsftngxa08!tkmsftngp01!tkmsftngp09
>Xref: cpmsftngxa08
microsoft.public.dotnet.framework.aspnet.webcontrols:6386
>X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.webcontrols
Thanks again!
Brad
P.S. Kim, I thought about a custom control but the actual control and the
integration with other objects in the web project didn't make sense to put
the time into a control (but that could change).
""Mike Moore [MS]"" <mic...@online.microsoft.com> wrote in message
news:yKXbcgHdCHA.2320@cpmsftngxa06...
In this context, making a custom controls is not necessary but still very
convinient.
It will enable you to add or remove more meaningfull collections of
controls: Removing the customcontrol will clear all childcontrols as well,
re-instancing will add it all in one single process - without needing loops
or recursions to search for the controls in question.
Kim :o)
--
Put an end to Outlook Express's messy quotes with this automated fix!
· http://flash.to/oe-quotefix/ ·
Brian
"Kim Bach Petersen" <msn...@kensho.dk> wrote in message news:<uELG0BUdCHA.2248@tkmsftngp11>...
The original question was how to modify a dynamically created control
without disabling server events associated with the control. The sample
code demonstrated one way to do this. The sample does not address
ViewState. So, you asked how the sample sets ViewState. The answer is that
none of the code in the sample addresses ViewState.
Does that answer your question?
Thank you, Mike Moore
Microsoft, ASP.NET
This posting is provided "AS IS", with no warranties, and confers no rights.
--------------------
>From: ripcu...@yahoo.com (Brian Chapman)
>Newsgroups: microsoft.public.dotnet.framework.aspnet.webcontrols
>Subject: Re: Dynamic Controls - how to replace after their events fire
>Date: 23 Oct 2002 12:05:06 -0700
>Organization: http://groups.google.com/
>Lines: 19
>Message-ID: <2ea64ade.02102...@posting.google.com>
>References: <eKR#e1UcCHA.2052@tkmsftngp12> <xYJN8e7cCHA.1904@cpmsftngxa06>
<OrvI208cCHA.1652@tkmsftngp09> <OzFYyYDdCHA.392@tkmsftngp09>
<yKXbcgHdCHA.2320@cpmsftngxa06> <uRpinbKdCHA.1004@tkmsftngp08>
<uELG0BUdCHA.2248@tkmsftngp11>
>NNTP-Posting-Host: 63.109.229.13
>Content-Type: text/plain; charset=ISO-8859-1
>Content-Transfer-Encoding: 8bit
>X-Trace: posting.google.com 1035399906 9335 127.0.0.1 (23 Oct 2002
19:05:06 GMT)
>X-Complaints-To: groups...@google.com
>NNTP-Posting-Date: 23 Oct 2002 19:05:06 GMT
>Path:
cpmsftngxa08!tkmsftngp01!newsfeed00.sul.t-online.de!t-online.de!newsfeed.fre
enet.de!newsfeed.news2me.com!newsfeed-west.nntpserver.com!hub1.meganetnews.c
om!nntpserver.com!telocity-west!TELOCITY!sn-xit-03!sn-xit-01!sn-xit-04!super
news.com!postnews1.google.com!not-for-mail
>Xref: cpmsftngxa08
microsoft.public.dotnet.framework.aspnet.webcontrols:6629
>X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.webcontrols
>
I have a page with one user control (user control added at design
time). The user control consists of a panel added at design time and
a bunch of linkbuttons added dynamically in either the page_load or in
the event handler when one of the existing linkbuttons is clicked.
(this is supposed to turn out like a tree view for browsing categories
in a catalog - we're using commerce server 2002.)
when the page is hit the first time, the "root categories" are loaded
into linkbuttons in page_load (using a helper method) and the command
events are registered for those buttons.
when a button is clicked the page re-loads (the buttons are added
again in page_load) and then the event fires. the event handler
causes the buttons to be loaded again and a second level of buttons
(sub-categories) is loaded below the button that was clicked (if it
has any sub-categories) in a recursive fashion.
this pattern should theoretically accomodiate n levels of hierarchy.
the problem (one of them) is that it takes 2 clicks on each link
button for the event to actually be fired (with the exception of the
first time the pages loads).
viewstate is disabled. it doesn't seem to matter where i load the
buttons (page_init, page_load, etc) because i get the same result. i
thought i understood the page processing stages, but i have a feeling
that's where i'm missing out!
can you describe how a tree view control could be built using this
type of method or tell me where i might be going wrong? i'll try to
put some code together to show what is happening.
thanks in advance. Brian
mic...@online.microsoft.com ("Mike Moore [MS]") wrote in message news:<dxSM9WveCHA.2280@cpmsftngxa08>...
QUESTION
In either the page init or load, I dynamically add some controls which have
events. Also, in the control events, I sometimes add yet additional
controls. The problem is that all the additional controls have to be
clicked twice in order to get their events to fire.
ANSWER
I may need to see the code sample you said you are working on to give you a
solution. Here's my first idea.
In order for ASP.NET to fire an event for a dynamically added control, that
control needs to be re-added during either init or load (preferably init).
I think you need to keep track of which controls you are adding in your
control events so that you can re-add them in the init event with each
subsequent execution of the page. Session variables might be a good place
for this. With session variables, just put some data (like text) into the
session variables and then use that data in the init function to recreate
the controls.
HTH.
Thank you, Mike Moore
Microsoft, ASP.NET
This posting is provided "AS IS", with no warranties, and confers no rights.
--------------------
>From: ripcu...@yahoo.com (Brian Chapman)
>Newsgroups: microsoft.public.dotnet.framework.aspnet.webcontrols
>Subject: Re: Dynamic Controls - how to replace after their events fire
>Date: 26 Oct 2002 09:11:12 -0700
>Organization: http://groups.google.com/
>Lines: 103
>Message-ID: <2ea64ade.02102...@posting.google.com>
>References: <eKR#e1UcCHA.2052@tkmsftngp12> <xYJN8e7cCHA.1904@cpmsftngxa06>
<OrvI208cCHA.1652@tkmsftngp09> <OzFYyYDdCHA.392@tkmsftngp09>
<yKXbcgHdCHA.2320@cpmsftngxa06> <uRpinbKdCHA.1004@tkmsftngp08>
<uELG0BUdCHA.2248@tkmsftngp11>
<2ea64ade.02102...@posting.google.com>
<dxSM9WveCHA.2280@cpmsftngxa08>
>NNTP-Posting-Host: 12.228.165.217
>Content-Type: text/plain; charset=ISO-8859-1
>Content-Transfer-Encoding: 8bit
>X-Trace: posting.google.com 1035648672 13029 127.0.0.1 (26 Oct 2002
16:11:12 GMT)
>X-Complaints-To: groups...@google.com
>NNTP-Posting-Date: 26 Oct 2002 16:11:12 GMT
>Path:
cpmsftngxa09!cpmsftngxa06!tkmsftngp01!newsfeed00.sul.t-online.de!t-online.de
!news.stealth.net!news.stealth.net!news.maxwell.syr.edu!sn-xit-03!sn-xit-06!
sn-xit-08!sn-xit-04!supernews.com!postnews1.google.com!not-for-mail
>Xref: cpmsftngxa09
microsoft.public.dotnet.framework.aspnet.webcontrols:6693
>X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.webcontrols
Thanks for the help, but I still haven't been able to figure this
out...this isn't a critical problem, I just want to understand what is
happening!
Here is some sample code using a custom control instead of a user
control (same problem). (link to code is at the bottom of the post)
Description:
In Page_Init, a web form loads a custom control containing link
buttons for a group of menu items. The user clicks on the "Links"
item and the command event is caught by the menu control which then
fires a custom event which is caught by the page. When the page
catches the event, it calls "LoadModule(...)" passing in the name of
the custom control to load, in this case, the "Links" control. The
links control is dynamically created and loaded in to a placeholder
control. A key is added to viewstate to note the control that was
most recently loaded. This key is checked in the Page_Load event so
the control can be reloaded each time the page is created.
The links control displays a datagrid that contains a list of
categories that the user can select. The user selects a category and
the data grid command event is fired. The control catches the event
and builds a second data grid with the links from the category that
was selected. Everything works fine. The user can select different
categories and the links show up. NOTE: I don't know if the design is
not correct and this is just working by chance.
If the user clicks the "Links" button in the menu control a second
time (or any number of times), it then takes 2 clicks on the link
category before the links will display.
So my question is, why?
Here is a link to the code: (code behind for the web page and the code
for the control)
http://brianchapman.homeip.net/bpweb/dropbox/code.zip
THANKS!
Brian
mic...@online.microsoft.com ("Mike Moore [MS]") wrote in message news:<Xb4$W5rfCHA.2484@cpmsftngxa08>...
I looked through your code a bit, but I did not to fully study it. The
code-behind for the ASPX page shows that it has two place holders actually
on the page. Then it dynamically adds a "MenuControl" that is from
Microsoft Commerce Server (that's the only control I could find with that
name).
The custom control has two classes. The first one loads a dataset from an
XML file. It includes a couple DataGrid controls and an HtmlTable control.
It looks like it loads the DataGrids with data from the XML file and then
it puts the DataGrids into cells inside the HtmlTable. The second class is
a custom definition of eventargs which does not appear to be used anywhere.
In all, this isn't a very easy sample to work with, especially within the
somewhat limited scope of newsgroup posts. However, I did see one line that
looked suspicious: PlaceHolderModules.Controls.Clear();
If you look earlier in this same thread, we found that we had to remove
controls, not just clear them. Here's a snippet from the code sample in the
earlier post:
Public Sub RemoveAll(ByRef container As Control)
Dim ctl As Control
Dim x As Integer
For x = container.Controls.Count - 1 To 0 Step -1
ctl = container.Controls(x)
If ctl.HasControls Then
'do a recursive remove, we are removing the controls in the
container
'before removing the container
RemoveAll(ctl)
End If
container.Controls.Remove(ctl)
Next
End Sub
End Class
---
You wrote that the basics of your problem is a dynamically added control
which has an event that dynamically adds a custom control that also has an
event. The way I would approach this is to make it dramatically simpler. No
commerce server controls, or XML, or nested tables.
I would use a regular web button control as my initial dynamically added
control. Then I would create a very simple custom control to be added by
the server onclick event of my button. This custom control would have no
more than the minimum necessary to be visible on the client and to raise an
event. Perhaps I might have it render the HTML for a submit button to the
client.
I'm sorry that I can't study your sample in depth and I hope this helps.
Good luck with your project.
Thank you, Mike Moore
Microsoft, ASP.NET
This posting is provided "AS IS", with no warranties, and confers no rights.
--------------------
>From: ripcu...@yahoo.com (Brian Chapman)
>Newsgroups: microsoft.public.dotnet.framework.aspnet.webcontrols
>Subject: Re: Dynamic Controls - how to replace after their events fire
>Date: 6 Nov 2002 16:52:07 -0800
>Organization: http://groups.google.com/
>Lines: 72
>Message-ID: <2ea64ade.02110...@posting.google.com>
>References: <eKR#e1UcCHA.2052@tkmsftngp12> <xYJN8e7cCHA.1904@cpmsftngxa06>
<OrvI208cCHA.1652@tkmsftngp09> <OzFYyYDdCHA.392@tkmsftngp09>
<yKXbcgHdCHA.2320@cpmsftngxa06> <uRpinbKdCHA.1004@tkmsftngp08>
<uELG0BUdCHA.2248@tkmsftngp11>
<2ea64ade.02102...@posting.google.com>
<dxSM9WveCHA.2280@cpmsftngxa08>
<2ea64ade.02102...@posting.google.com>
<Xb4$W5rfCHA.2484@cpmsftngxa08>
>NNTP-Posting-Host: 12.228.165.217
>Content-Type: text/plain; charset=ISO-8859-1
>Content-Transfer-Encoding: 8bit
>X-Trace: posting.google.com 1036630327 16356 127.0.0.1 (7 Nov 2002
00:52:07 GMT)
>X-Complaints-To: groups...@google.com
>NNTP-Posting-Date: 7 Nov 2002 00:52:07 GMT
>Path:
cpmsftngxa09!cpmsftngxa08!tkmsftngp01!newsfeed00.sul.t-online.de!t-online.de
!newsfeed.icl.net!newsfeed.fjserv.net!newsfeed.icl.net!newsfeed.fjserv.net!n
ewsfeed1.cidera.com!Cidera!telocity-west!TELOCITY!sn-xit-03!sn-xit-01!sn-xit
-04!supernews.com!postnews1.google.com!not-for-mail
>Xref: cpmsftngxa09
microsoft.public.dotnet.framework.aspnet.webcontrols:6967
>X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.webcontrols
I found that the control added like this:
Me.Controls(1).Controls.Add(TextBox1)
Works and maintains its state through the post-back. This is adding
the control to the Page container, right? There's no control over the
layout of the controls. But when I similarly add controls to a
container
that was also created dynamically, such as a Panel or a Table control,
the control is lost upon postback. Is there a way around this?
Below is a link to a post that explains more fully what I want to do.
Thanks,
"Brad" <nos...@co.lane.or.us> wrote in message news:<OrvI208cCHA.1652@tkmsftngp09>...
I apologize for the confusion...I've been using the same project for
all kinds of tests, so things became a little screwed up!
As you suggested, I created a very simple example that exhibits the
same behavior. I used a UserControl instead because it was easier.
Please let me know if you have any suggestions! Thanks. Brian
WebForm:
public class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.PlaceHolder PlaceHolder1;
protected System.Web.UI.WebControls.PlaceHolder PlaceHolder2;
public WebForm1()
{
this.Load += new System.EventHandler(this.Page_Load);
}
private void Page_Load(object sender, System.EventArgs e)
{
if ( (String)ViewState["Control"] != null &&
! ((String)ViewState["Control"]).Equals(""))
{
PlaceHolder2.Controls.Add(LoadControl((String)ViewState["Control"]));
}
}
protected void Page_Init(object sender, System.EventArgs args)
{
LinkButton lb = new LinkButton();
lb.Text = "Click";
lb.Click += new System.EventHandler(this.OnPageLinkButtonClicked);
PlaceHolder1.Controls.Add(lb);
}
protected void OnPageLinkButtonClicked(object sender,
System.EventArgs e)
{
foreach ( Control c in PlaceHolder2.Controls )
{
PlaceHolder2.Controls.Remove(c);
}
PlaceHolder2.Controls.Add(LoadControl("WebUserControl2_TEST.ascx"));
ViewState.Add("Control", "WebUserControl2_TEST.ascx");
}
User Control:
public abstract class WebUserControl2_TEST : System.Web.UI.UserControl
{
public WebUserControl2_TEST()
{
this.Init += new System.EventHandler(this.Page_Init);
}
private void Page_Init(object sender, System.EventArgs e)
{
LinkButton b = new LinkButton();
b.Text = "Ctrl";
b.Click += new System.EventHandler(this.OnButtonClick);
Controls.Add(b);
}
protected void OnButtonClick(object sender, System.EventArgs e)
{
Label l = new Label();
l.Text = "Test";
Controls.Add(l);
}
}
mic...@online.microsoft.com ("Mike Moore [MS]") wrote in message news:<gUQpB56hCHA.2704@cpmsftngxa06>...
If you look at the sample code I posted (in response to the message
you responded to from Mike) you see that to make sure that the
dynamically loaded usercontrol is re-added to the page each time, that
I store in ViewState that it has been added. I then re-load the
control for every post back after that. I think you'll have to do the
same, just with a more information in ViewState.
It get's pretty tricky when you're adding lots of controls
dynamically!
Brian
mong...@hotmail.com (Liz Patton) wrote in message news:<40870380.02110...@posting.google.com>...
Brian
ripcu...@yahoo.com (Brian Chapman) wrote in message news:<2ea64ade.0211...@posting.google.com>...
I'm sorry for taking so long to get back to you. I just looked at your new
code. It is much easier to work with, thank you.
I created a user control with your code and pasted your web form code into
the code-behind of a web form. I changed the class names to match the name
of my web form.
When I tried your code, I found that the web-form code Page_Init event did
not fire. I then noticed that you removed the auto-generated OnInit event
and replaced it with an event with the same name as the class. You did this
with both the web form code and the user control code. So, added the
following line to the event with the same name as the class:
this.Init += new System.EventHandler(this.Page_Init);
Now I have the following behavior:
1 browse the page -- it shows a link button with text "click"
2 click the button -- it shows two buttons, "click" and "ctrl"
3 click "ctrl" -- it shows "click", "ctrl" and "test" (which is a label)
4 click "click" again -- it shows "click" and "ctrl"
5 click "ctrl" -- it FAILS to show test (just "click" and "ctrl")
6 click "ctrl" again -- it shows all three controls (including "test") as
it's supposed to
So, the problem is the second attempt to click the "ctrl" button fails to
display "test".
This means that, in step 5, the button dynamically added to the user
control fails to fire its own event.
----
I've looked at this and have not yet determined why it is happening. I will
look into it further tomorrow.
Thank you, Mike Moore
Microsoft, ASP.NET
This posting is provided "AS IS", with no warranties, and confers no rights.
--------------------
>From: ripcu...@yahoo.com (Brian Chapman)
>Newsgroups: microsoft.public.dotnet.framework.aspnet.webcontrols
>Subject: Re: Dynamic Controls - how to replace after their events fire
>Date: 10 Nov 2002 11:07:21 -0800
>Organization: http://groups.google.com/
>Lines: 143
>Message-ID: <2ea64ade.02111...@posting.google.com>
>References: <eKR#e1UcCHA.2052@tkmsftngp12> <OrvI208cCHA.1652@tkmsftngp09>
<OzFYyYDdCHA.392@tkmsftngp09> <yKXbcgHdCHA.2320@cpmsftngxa06>
<uRpinbKdCHA.1004@tkmsftngp08> <uELG0BUdCHA.2248@tkmsftngp11>
<2ea64ade.02102...@posting.google.com>
<dxSM9WveCHA.2280@cpmsftngxa08>
<2ea64ade.02102...@posting.google.com>
<Xb4$W5rfCHA.2484@cpmsftngxa08>
<2ea64ade.02110...@posting.google.com>
<gUQpB56hCHA.2704@cpmsftngxa06>
<2ea64ade.0211...@posting.google.com>
>NNTP-Posting-Host: 12.228.165.217
>Content-Type: text/plain; charset=ISO-8859-1
>Content-Transfer-Encoding: 8bit
>X-Trace: posting.google.com 1036955242 10084 127.0.0.1 (10 Nov 2002
19:07:22 GMT)
>X-Complaints-To: groups...@google.com
>NNTP-Posting-Date: 10 Nov 2002 19:07:22 GMT
>Path:
cpmsftngxa06!tkmsftngp01!newsfeed00.sul.t-online.de!t-online.de!newsfeed.icl
net!newsfeed.fjserv.net!c02.atl3!news.webusenet.com!telocity-west!TELOCITY!
sn-xit-03!sn-xit-01!sn-xit-04!supernews.com!postnews1.google.com!not-for-mai
l
>Xref: cpmsftngxa06
microsoft.public.dotnet.framework.aspnet.webcontrols:7050
>X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.webcontrols
As far as moving the registration of the Init event to the constructor
(name of the web form)...I did that because VS.NET occassionally was
not auto-generating the OnInit event. I looked around for a bit and
found that the IBuySpyPortal code was registering for the Init event
in the constructor...so I went with that method. It seems to have
worked so far.
Thanks for the help, and please let me know what you find.
Brian
mic...@online.microsoft.com ("Mike Moore [MS]") wrote in message news:<9exWrwEjCHA.2340@cpmsftngxa08>...
QUESTION
I have a dynamically added button control (btn). The second time I click
this button, its server-side click event fails to execute.
First, my form already has a button (Button1). The server-side click event
for "Button1" adds "btn". On further post backs, "btn" is re-added in the
Page_Load event. The failure occurs the first time "btn" is added via the
Page_Load event, when it was previously added in the Button1 click event.
ANSWER
It turns out that this can happen any time that a control is dynamically
added in different places within your code. In this case, it is sometimes
added in the first button's click event and other times added in the
Page_Load event. Here are the related snippets from your code sample:
* Page_Load
PlaceHolder2.Controls.Add(LoadControl((String)ViewState["Control"]));
//[where the value from ViewState is: "WebUserControl2_TEST.ascx"
* OnPageLinkButtonClicked
PlaceHolder2.Controls.Add(LoadControl("WebUserControl2_TEST.ascx"));
The fix for this is to give the control an ID in your code so that it
receives the same ID every time it is added. Otherwise, .NET will determine
an ID for you. This is generally fine if your control is always added by
the same line of code. However, your control is sometimes added by a line
of code in Page_Load, and other times added in a line of code in
OnPageLinkButtonClicked.
Here is the replacement code snippets that fix this problem:
* Page_Load
System.Web.UI.UserControl ctl = (System.Web.UI.UserControl)
LoadControl((String)ViewState["Control"]);
ctl.ID = "MyControl";
PlaceHolder2.Controls.Add(ctl);
//[where the value from ViewState is: "WebUserControl2_TEST.ascx"
* OnPageLinkButtonClicked
System.Web.UI.UserControl ctl = (System.Web.UI.UserControl)
LoadControl("WebUserControl2_TEST.ascx");
ctl.ID = "MyControl";
PlaceHolder2.Controls.Add(ctl);
CODE SAMPLE:
***** User control (WebUserControl2_TEST.ascx)
* Do nothing. Just leave it empty, as it already is.
***** Code-behind for WebUserControl2_TEST.ascx
namespace nTest3
{
using System;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
/// <summary>
/// Summary description for WebUserControl2_TEST.
/// </summary>
public abstract class WebUserControl2_TEST : System.Web.UI.UserControl
{
public WebUserControl2_TEST()
{
this.Init += new System.EventHandler(this.Page_Init);
}
private void Page_Init(object sender, System.EventArgs e)
{
LinkButton b = new LinkButton();
b.Text = "Ctrl";
b.Click += new System.EventHandler(this.OnButtonClick);
Controls.Add(b);
}
protected void OnButtonClick(object sender, System.EventArgs e)
{
Label l = new Label();
l.Text = "Test";
Controls.Add(l);
}
}
}
***** ASPX (wc2_test.aspx)
* Add two place holder controls to the ASPX page
***** Code-behind for wc2_test.aspx
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
namespace nTest3
{
/// <summary>
/// Summary description for wc2_test.
/// </summary>
public class wc2_test : System.Web.UI.Page
{
protected System.Web.UI.WebControls.PlaceHolder PlaceHolder1;
protected System.Web.UI.WebControls.PlaceHolder PlaceHolder2;
public wc2_test()
{
this.Init += new System.EventHandler(this.Page_Init);
this.Load += new System.EventHandler(this.Page_Load);
}
private void Page_Load(object sender, System.EventArgs e)
{
if ( (String)ViewState["Control"] != null &&
! ((String)ViewState["Control"]).Equals(""))
{
System.Web.UI.UserControl ctl = (System.Web.UI.UserControl)
LoadControl((String)ViewState["Control"]);
ctl.ID = "MyControl";
PlaceHolder2.Controls.Add(ctl);
}
}
protected void Page_Init(object sender, System.EventArgs args)
{
LinkButton lb = new LinkButton();
lb.Text = "Click";
lb.Click += new System.EventHandler(this.OnPageLinkButtonClicked);
PlaceHolder1.Controls.Add(lb);
}
protected void OnPageLinkButtonClicked(object sender,
System.EventArgs e)
{
foreach ( Control c in PlaceHolder2.Controls )
{
PlaceHolder2.Controls.Remove(c);
}
System.Web.UI.UserControl ctl = (System.Web.UI.UserControl)
LoadControl("WebUserControl2_TEST.ascx");
ctl.ID = "MyControl";
PlaceHolder2.Controls.Add(ctl);
ViewState.Add("Control", "WebUserControl2_TEST.ascx");
}
}
}
***** end of code sample
Thank you, Mike Moore
Microsoft, ASP.NET
This posting is provided "AS IS", with no warranties, and confers no rights.
--------------------
>From: ripcu...@yahoo.com (Brian Chapman)
>Newsgroups: microsoft.public.dotnet.framework.aspnet.webcontrols
>Subject: Re: Dynamic Controls - how to replace after their events fire
>Date: 15 Nov 2002 12:27:06 -0800
>Organization: http://groups.google.com/
>Lines: 256
>Message-ID: <2ea64ade.02111...@posting.google.com>
>References: <eKR#e1UcCHA.2052@tkmsftngp12> <uRpinbKdCHA.1004@tkmsftngp08>
<uELG0BUdCHA.2248@tkmsftngp11>
<2ea64ade.02102...@posting.google.com>
<dxSM9WveCHA.2280@cpmsftngxa08>
<2ea64ade.02102...@posting.google.com>
<Xb4$W5rfCHA.2484@cpmsftngxa08>
<2ea64ade.02110...@posting.google.com>
<gUQpB56hCHA.2704@cpmsftngxa06>
<2ea64ade.0211...@posting.google.com>
<2ea64ade.02111...@posting.google.com>
<9exWrwEjCHA.2340@cpmsftngxa08>
>NNTP-Posting-Host: 208.247.148.12
>Content-Type: text/plain; charset=ISO-8859-1
>Content-Transfer-Encoding: 8bit
>X-Trace: posting.google.com 1037392026 10724 127.0.0.1 (15 Nov 2002
20:27:06 GMT)
>X-Complaints-To: groups...@google.com
>NNTP-Posting-Date: 15 Nov 2002 20:27:06 GMT
>Path:
cpmsftngxa08!tkmsftngp01!newsfeed00.sul.t-online.de!t-online.de!news-spur1.m
axwell.syr.edu!news.maxwell.syr.edu!newsfeed-west.nntpserver.com!hub1.megane
tnews.com!nntpserver.com!telocity-west!TELOCITY!sn-xit-03!sn-xit-01!sn-xit-0
4!supernews.com!postnews1.google.com!not-for-mail
>Xref: cpmsftngxa08
microsoft.public.dotnet.framework.aspnet.webcontrols:7240
>X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.webcontrols