ASP button control firing - asp.net

The problem im having is a little complicated to explain, so please bear with me. I have 2 button controls. In the page load, I wanted to know what button created a postback on the page load. Through research I have found this snippet below and it works as expected. So here is my scenario of events that occur when click on the button.
1. Click the button does a postback
2. Runs the function below and tell me the id of the button
3. Runs the clicked event handlers for that button
Protected Sub btnCalc_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnCalc.Click
' Do this
End Sub
The problem comes in when I click the second button, it does steps 1 and 2 but NEVER DOES 3. Through testing, I have that it only does 1, 2, and 3 on the first button clicked. I have no clue why this is happening?
Function GetPostBackControlName() As String
Dim control As Control = Nothing
Dim ctrlname As String = Page.Request.Params("__EVENTTARGET")
If ctrlname <> Nothing AndAlso ctrlname <> [String].Empty Then
control = Page.FindControl(ctrlname)
Else
Dim ctrlStr As String = [String].Empty
Dim c As Control = Nothing
For Each ctl As String In Page.Request.Form
c = Page.FindControl(ctl)
If TypeOf c Is System.Web.UI.WebControls.Button Then
control = c
Exit For
End If
Next
End If
Try
Return control.ID.ToString
Catch
Return ""
End Try
End Function

You really should look into just assigning Click event handlers to your buttons. Asp.net was designed purposely so that you wouldn't have to parse through the request object like you are doing above.

Related

Missing Controls in page after timer method ticks

I have some code that handles a timer method, that just updates a label and changes it to a last updated at this time.
Protected Sub specialNotesTimer_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles specialNotesTimer.Tick
Label1.Text = "Panel refreshed at: " + DateTime.Now.ToLongTimeString()
End Sub
When it ticks however, any other control on the page cannot be found via a button press. Image buttons or my other dynamically created controls, w.e the case, are missing.
I have a function that finds the fired control on the page, then returns the control so I can determine what to do
Public Shared Function GetPostBackControl(ByVal thePage As Page) As Control
Dim myControl As Control = Nothing
Dim ctrlName As String = thePage.Request.Params.Get("__EVENTTARGET")
If ((ctrlName IsNot Nothing) And (ctrlName <> String.Empty)) Then
myControl = thePage.FindControl(ctrlName)
Else
For Each Item As String In thePage.Request.Form
Dim c As Control = thePage.FindControl(Item)
If (TypeOf (c) Is System.Web.UI.WebControls.Button) Then
myControl = c
End If
Next
End If
Return myControl
End Function
This works before the timer.tick, but not after. The control won't be listed as an Item in thePage.Request.Form, and it'll throw a null exception, when I know the control is there.

Dynamically generated code-behind button won't fire its event

I have a series of controls (3 labels, 3 text boxes, and 2 buttons) that are created when the user clicks a button on my page. The page does its postback with the commands that will generate these controls. However, when I fill in my textboxes and click one of the newly generated buttons (btnCreate), nothing happens, and the page just reloads once again.
What I want to happen is that when the user clicks btnCreate, it fires its function, and puts the TextBox.Text into a database. But again, when btnCreate is clicked, nothing happens.
Here is the code for the generated buttons (It's the same function that generates the text boxes, which I've excluded here):
Protected Sub createSpecialNotes()
Dim btnCreate As Button = New Button
Dim btnClear As Button = New Button
'Place properties
lblSubject.Text = "subject"
lblSubject.ID = "lblSubject"
lblSubject.Width = 700
lblAgenda.Text = "Agenda Note"
lblAgenda.ID = "lblAgenda"
lblAgenda.Width = 700
lblMinutes.Text = "Minutes Note"
lblMinutes.ID = "lblMinutes"
lblMinutes.Width = 700
btnCreate.Text = "Create"
btnCreate.ID = "btnCreate"
btnClear.Text = "Clear"
btnClear.ID = "btnClear"
'Add handlers for buttons
AddHandler btnCreate.Click, AddressOf btnCreate_Click
AddHandler btnClear.Click, AddressOf btnClear_Click
plhCreateSpecialNotes.Controls.Add(btnCreate)
plhCreateSpecialNotes.Controls.Add(btnClear)
End Sub
And for the sake of simplicity, let's just say btnCreate needs only to display the textboxes' contents.
Edit1: The call for create special notes is on page_preInit. It's call consists of the following
Protected Sub Page_PreInit(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreInit
'Find the control that was fired
Dim controlFired As Control = GetPostBackControl(Me.Page)
If (controlFired IsNot Nothing) Then
If (controlFired.ClientID.ToString() = "btnCreateSpecial") Then
Call createSpecialNotes()
End If
If (controlFired.ClientID.ToString() = "btnCreate") Then
'i've tried putting things here to no avail.
End If
End If
End Sub
The function getpostbackcontrol looks like this
Public Shared Function GetPostBackControl(ByVal thePage As Page) As Control
Dim myControl As Control = Nothing
Dim ctrlName As String = thePage.Request.Params.Get("__EVENTTARGET")
If ((ctrlName IsNot Nothing) And (ctrlName <> String.Empty)) Then
myControl = thePage.FindControl(ctrlName)
Else
For Each Item As String In thePage.Request.Form
Dim c As Control = thePage.FindControl(Item)
If (TypeOf (c) Is System.Web.UI.WebControls.Button) Then
myControl = c
End If
Next
End If
Return myControl
End Function
I hope this helps to clear things up as to why I'm having trouble.
What would be really useful here is to know when you're calling createSpecialNotes(). But most probably what you are missing is the life-cycle of the page.
Make sure createSpecialNotes() is called OnInit of your page. Anything after that is too late and your event handler won't be fired.
If OnLoad of your page is reached and you haven't yet bound the handler to your control, then it won't be fired.
I recommend that you read this article carefully. http://msdn.microsoft.com/en-us/library/ms178472.aspx

Button control not firing

The problem im having is a little complicated to explain, so please bear with me. I have 2 button controls. In the page load, I wanted to know what button created a postback on the page load. Through research I have found this snippet below and it works as expected. So here is my scenario of events that occur when click on the button.
1. Click the button does a postback
2. Runs the function below and tell me the id of the button
3. Runs the clicked event handlers for that button
Protected Sub btnCalc_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnCalc.Click
' Do this
End Sub
The problem comes in when I click the second button, it does steps 1 and 2 but NEVER DOES 3. Through testing, I have that it only does 1, 2, and 3 on the first button clicked. I have no clue why this is happening?
Function GetPostBackControlName() As String
Dim control As Control = Nothing
Dim ctrlname As String = Page.Request.Params("__EVENTTARGET")
If ctrlname <> Nothing AndAlso ctrlname <> [String].Empty Then
control = Page.FindControl(ctrlname)
Else
Dim ctrlStr As String = [String].Empty
Dim c As Control = Nothing
For Each ctl As String In Page.Request.Form
c = Page.FindControl(ctl)
If TypeOf c Is System.Web.UI.WebControls.Button Then
control = c
Exit For
End If
Next
End If
Try
Return control.ID.ToString
Catch
Return ""
End Try
End Function

Accessing dynamically created checkbox in user control from container page

I am building a wizard in asp.net. I have an main aspx page which will have NEXT and PREVIOUS button for Navigation. On click of each NEXT or PREVIOUS appropriate user control will be loaded.
In one user control I have to create dynamic checkboxes as shown below:
Public Class ucQuestion
Inherits System.Web.UI.UserControl
#Region "UserControl Events"
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Try
If Not (Page.IsPostBack) Then
AddControls(0)
End If
Catch ex As Exception
Throw ex
End Try
End Sub
#End Region
Protected Friend Sub AddControls(ByVal iListQuestionCount As Integer)
Try
Dim oExam As New BusinessObject.Wizard.ExamVM
If (System.Web.HttpContext.Current.Session(BusinessLayer.Constants.WizardObjectCollection) IsNot Nothing) Then
oExam = DirectCast(System.Web.HttpContext.Current.Session(BusinessLayer.Constants.WizardObjectCollection), BusinessObject.ExamWizard.ExamVM)
End If
'divQuestion.Controls.Clear()
Dim ctrl As New Literal
ctrl.ID = "lit" + iListQuestionCount.ToString()
ctrl.Text = oExam.Wizard.ExamQuestions(iListQuestionCount).Label
divQuestion.Controls.Add(ctrl)
For iLoopChildCount As Integer = 0 To oExam.Wizard.ExamQuestions(iListQuestionCount).Choices.Count - 1
Dim childctrl As New CheckBox
'childctrl.AutoPostBack = True
childctrl.ID = "chk" + (iLoopChildCount + 1).ToString()
childctrl.Text = oExam.Wizard.ExamQuestions(iListQuestionCount).Choices(iLoopChildCount).Label
childctrl.Checked = oExam.Wizard.ExamQuestions(iListQuestionCount).Choices(iLoopChildCount).IsSelected
'AddHandler childctrl.CheckedChanged, AddressOf OnCheckedClick
divQuestion.Controls.Add(childctrl)
Next
Catch ex As Exception
Throw ex
End Try
End Sub
NoW the problem is in my Main.aspx page if user has selected any checkbox in usercontrol I want to save the value in session on NEXT button Navigation click event.
I tried following code in NEXT Button Click but it was unsucessfull.
For iLoopChildCount As Integer = 0 To oExamQuestions(ListIndex).Choices.Count - 1
Dim ctrl As Control
If (ucQuestion1.FindControl("chk" + (iLoopChildCount + 1).ToString()) IsNot Nothing) Then
ctrl = DirectCast(ucQuestion1.FindControl("chk" + (iLoopChildCount + 1).ToString()), CheckBox)
If (DirectCast(ctrl, CheckBox).Checked) Then
oBallotQuestions(ListIndex).Choices(iLoopChildCount).IsSelected = True
End If
End If
Next
That's the hard way.
Here is the easy way.
Define an interface and implement it in the User Control that represents this action. This might be GetNamesOfSelectedValues or whatever is appropriate. (Technically an interface isn't required, but I find it good practice and it makes for "more well defined contracts" in many cases.)
Use the interface defined on said Child in the Parent page code. Use this only after the OnLoad of the Child Control (which happens after the page load event) or the controls will not be restored yet.
That is, the parent should not know about any controls in the custom User Control.
This approach works well.

Creating buttons dynamically in ListView

I have a following problem. I have a ListView which returns data from SQL table. One of its columns looks like "Ambient/Trance/Goa Trance/House".
All i want to do is parse this column and create buttons for each value, for example a button for "Ambient", a button for "Trance", etc.
I tried to create buttons in ItemDataBound event in the following way:
Dim ListView_Albums_PlaceHolder_Artists As PlaceHolder = e.Item.FindControl("ListView_Albums_PlaceHolder_Artists")
Dim Artists As String() = e.Item.DataItem("album_artists").ToString.Split("/")
Dim ArtistsN As String() = e.Item.DataItem("album_artists_n").ToString.Split("/")
Dim ListView_Albums_Literal_Artists As New Literal
If Artists.Length = 1 Then
ListView_Albums_Literal_Artists.Text = "Artist: "
Else
ListView_Albums_Literal_Artists.Text = "Artists: "
End If
ListView_Albums_PlaceHolder_Artists.Controls.Add(ListView_Albums_Literal_Artists)
For Integer1 As Integer = 0 To Artists.Length - 1
Dim ListView_Albums_LinkButton_Artist As New LinkButton
ListView_Albums_LinkButton_Artist.Text = ArtistsN(Integer1)
ListView_Albums_LinkButton_Artist.CommandName = "Artist"
ListView_Albums_LinkButton_Artist.CommandArgument = Artists(Integer1)
ListView_Albums_LinkButton_Artist.CssClass = "a-03"
ListView_Albums_PlaceHolder_Artists.Controls.Add(ListView_Albums_LinkButton_Artist)
Dim ListView_Albums_Literal As New Literal
ListView_Albums_Literal.Text = ", "
If Not Integer1 = Artists.Length - 1 Then
ListView_Albums_PlaceHolder_Artists.Controls.Add(ListView_Albums_Literal)
End If
Next
They created fine but they didn't work at all. I tried to Add Handler for Click or Command event but it also didn't help.
Please help me to solve my problem!
Edit:
As VinayC suggested I changed ItemDataBound to ItemCreated. That helped, but I faced another problem: as far as I understand e.Item.DataItem or, maybe, e.Item becomes Nothing on PostBacks so the buttons do not work.
How to solve that problem? Thanks once again!
I believe that buttons must be getting created late in page life cycle and hence not responding to events.
You may want to try moving your code in ItemCreated event and use ListView's ItemCommand event to trap these. Yet another suggestion is to assign (different) ID to your link buttons - for example
ListView_Albums_LinkButton_Artist.ID = "A" & Artists(Integer1)
In case, you want to attach an click event handler directly to buttons then ID is must.
So, I solved my problem. The solution wasn't simple but here it is:
In ItemCreated event I firstly count the number of buttons, then save it to ViewState, and only then I create buttons. I had to save the number of buttons to ViewState because on every postback e.Item.DataItem becomes Nothing.
Maybe there is a simplier solution but I found only that one...
Sub OnItemCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs)
Dim ListView_Albums_PlaceHolder_Artists As PlaceHolder = e.Item.FindControl("ListView_Albums_PlaceHolder_Artists")
If Not ListView_Albums_PlaceHolder_Artists Is Nothing Then
If Not e.Item.DataItem Is Nothing Then
ViewState("Length") = e.Item.DataItem("album_artists").ToString.Split("/").Length
End If
If Not ViewState("Length") Is Nothing Then
Dim Length As Integer = ViewState("Length")
For Integer1 As Integer = 0 To Length - 1
Dim ListView_Albums_LinkButton_Artist As New LinkButton
ListView_Albums_LinkButton_Artist.ID = "ListView_Albums_LinkButton_Artist_" & Integer1
ListView_Albums_PlaceHolder_Artists.Controls.Add(ListView_Albums_LinkButton_Artist)
Next
End If
End If
End Sub
Sub OnItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs)
Dim ListView_Albums_PlaceHolder_Artists As PlaceHolder = e.Item.FindControl("ListView_Albums_PlaceHolder_Artists")
If Not ListView_Albums_PlaceHolder_Artists Is Nothing Then
If Not e.Item.DataItem Is Nothing Then
Dim Artists As String() = e.Item.DataItem("album_artists").ToString.Split("/")
Dim Artists_N As String() = e.Item.DataItem("album_artists_n").ToString.Split("/")
For Integer1 As Integer = 0 To Artists.Length - 1
Dim ListView_Albums_LinkButton_Artist As LinkButton = e.Item.FindControl("ListView_Albums_LinkButton_Artist_" & Integer1)
ListView_Albums_LinkButton_Artist.CommandArgument = Artists(Integer1)
ListView_Albums_LinkButton_Artist.Text = Artists_N(Integer1)
ListView_Albums_LinkButton_Artist.CssClass = "a-03"
Next
End If
End If
End Sub

Resources