Developed a slightly dynamic page that builds a Question and Answer page based on information from a database. Everything works great except i cant get the RadioButtonList event to trigger with a minor MsgBox response to validate object sender and selected ListItem information.
Page_Load
If Not Page.IsPostBack Then
With Globals.tst
.GetBrandInformation(Page.RouteData.Values("brand"),
Page.RouteData.Values("year"),
Page.RouteData.Values("month"))
'Load up Question DataSet
For Each quest As Question In .Questions
Dim tr As New HtmlControls.HtmlTableRow
Dim td As New HtmlControls.HtmlTableCell
td.Attributes.Add("class", "tdQ") 'Add class attribute to <td> element, creating 'class="tdQ"'
Dim lbl As New Label
lbl.ID = "lbl" & quest.ID
lbl.Text = quest.Text
td.Controls.Add(lbl)
tr.Cells.Add(td)
tblContent.Rows.Add(tr)
tr = New HtmlControls.HtmlTableRow
td = New HtmlControls.HtmlTableCell
td.Attributes.Add("class", "tdA") 'Add class attribute to <td> element, creating 'class="tdA"'
Dim rbl As New RadioButtonList
rbl.ID = "rblT" & .ID & "_Q" & quest.ID
AddHandler rbl.SelectedIndexChanged, AddressOf rbl_SelectedIndexChanged 'Attach generic event handler to control
Dim li As New ListItem
'Load up Answer Dataset
For Each answ As Answer In quest.Answers
li.Text = answ.Value
li.Value = "T" & .ID & "-Q" & quest.ID & "-A" & answ.ID & "-C" & answ.Correct
'Add built ListItem to RadioButtonList
rbl.Items.Add(li)
li = New ListItem
Next
td.Controls.Add(rbl)
tr.Cells.Add(td)
tblContent.Rows.Add(tr)
Next
End With
'
End If
Below is the Generic Event Handler Logic i am trying to attach to the RadioButtonList(s).
Protected Sub rbl_SelectedIndexChanged(sender As Object, e As EventArgs)
MsgBox(CType(sender, RadioButtonList).ID & " Clicked.")
MsgBox("Radio Button Selected: " & CType(sender, RadioButtonList).ID & " is Correct? " & CType(sender, RadioButtonList).SelectedValue)
End Sub
Anyone see anything wrong with the design, or know why the Event is not being triggered?
Edited 2012-11-20
Ok changed the rbl object to do AutoPostBack = true but that made life even more unbearable ;) Then quickly reverted back as the Q&A list i have is randomly generated on the Questions and Answers so the end-user would be given a new random order of questions upon every click of the ListItem.
Although i am getting some response back from the call backs still not getting the JavaScript response i am expecting by using either a defined JavaScript file or inline Response.Write/ClientScript.Register.
Created a debugging method into the Content Page:
Public Shared Sub Show(msg As String, Optional pg As Page = Nothing)
Dim cmsg As String = msg.Replace("'", "\'")
Dim scr As String = "<script type=""text/javascript"">alert('" & cmsg & "');</script>"
If pg Is Nothing Then
pg = CType(HttpContext.Current.CurrentHandler, Page)
End If
If (pg IsNot Nothing) And Not (pg.ClientScript.IsClientScriptBlockRegistered("alert")) Then
pg.ClientScript.RegisterClientScriptBlock(GetType(Alert), "alert", scr)
End If
End Sub
On page Load this method fires and as expected, but when placed inside the SelectedIndexChanged event it never fires off.
Still perplexed on why it works on general execution but not triggered execution.
Userful Method for those that like to create .Net methods that implement Javascript. .Net Slave - Javascript Alert.Show Class
You have to take it OUT of the If Not Page.IsPostBack Then
this is because when you DO postback, the...
AddHandler rbl.SelectedIndexChanged, AddressOf rbl_SelectedIndexChanged
...needs to be rebound before it can fire.
So basically, remove the If Not Page.IsPostBack Then and End If.
Oh, and get rid of the MsgBox() code too - this will kill the page from doing anything. If you want to output an Alert() then do something like:
Dim script As String = String.Format("alert('{0}');", ""Radio Button Selected: " & CType(sender, RadioButtonList).ID & " is Correct? " & CType(sender, RadioButtonList).SelectedValue")
page.ClientScript.RegisterClientScriptBlock(page.[GetType](), "alert", script, True)
UPDATE:
you also want to set AutoPostback = true; on your RBL. This tells the page to postback as soon as it's changed. the handler only fires if AutoPostBack is true.
Related
When my ASP page is loaded I am reading data from a SQL database into a list of objects, then looping through this list and creating dynamic placeholders, updatepanels, textboxs and buttons which are then added to a main placeholder. Each updatepanel is set to conditional and the unique button is added to the scriptmanager. I tried to create async triggers dynamically but found this is not possible. Below is my code:
Dim plcComments As New PlaceHolder()
plcComments.ID = "plcComments" + Link.ID.ToString()
Dim updComments As New UpdatePanel()
updComments.ID = "updComments" + Link.ID.ToString()
updComments.UpdateMode = UpdatePanelUpdateMode.Conditional
Dim txtComment As New TextBox()
txtComment.ID = "txtComment" + Link.ID.ToString()
txtComment.Text = "txtComment " + Link.ID.ToString() 'Example text
updComments.ContentTemplateContainer.Controls.Add(txtComment)
Dim btnComment As New Button()
btnComment.ID = "btnComment" + Link.ID.ToString()
btnComment.Text = "btnComment" + Link.ID.ToString()
updComments.ContentTemplateContainer.Controls.Add(btnComment)
ScriptManager1.RegisterAsyncPostBackControl(btnComment)
plcComments.Controls.Add(updComments)
In a normal circumstance I understand you would have code behind for each button that acts a trigger. As these buttons are created dynamically with unique names, how can I react to each button when it is pressed?
After looking into the AddHandler function I came up with this dirty method:
AddHandler btnComment.Click, AddressOf Me.Button_Handler
This latches to each button as it is created, points back at the same sub routine, and creates the controls within the subroutine based upon the sender.
Protected Sub Button_Handler(sender As Object, e As EventArgs)
Dim Comment_ID As String = DirectCast(sender, Button).ID.ToString.Remove(0, 3)
Dim txtComment As TextBox = Me.FindControl("txt" & Comment_ID)
Dim plcComment As PlaceHolder = Me.FindControl("plc" & Comment_ID)
Dim updComment As UpdatePanel = Me.FindControl("upd" & Comment_ID)
End Sub
Probably not the cleanest or best way to do it but it works.
Good afternoon people have been trying to fill a dropdown using a sql command, until so good, when I click on the dropdown it shows all the items, but when I try to click on an item in the dropdown it always returns the first item in the dropdown .... follows the codes, what i want to do is get the selected value and item from the dropdown and save it on a label for future use.
I appreciate all the support possible,
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
utilizador.Text = Me.Context.User.Identity.Name
If (Not Page.IsPostBack) Then
escolhePerfil()
End If
'DropDownPerfil.DataBind()
lbperfil2.Text = DropDownPerfil.SelectedItem.Text
lbnome.Text = DropDownPerfil.SelectedValue
End Sub
Function escolhePerfil() As Boolean
Dim connstring As String = "Data Source=10.2.24.17;Persist Security Info=True;User ID=sa;Password=Pr0dUn1C0$qL;database=ePrimavera"
Dim SQLData As New System.Data.SqlClient.SqlConnection(connstring)
Dim cmdSelect As New System.Data.SqlClient.SqlCommand("SELECT u.WindowsUser,u.Email ,g.Description, u.Login FROM [ePrimavera].[dbo].[PLT_Users] as u,[ePrimavera].[dbo].[PLT_UserGroups] as ug, [ePrimavera].[dbo].[PLT_Groups] as g where u.ID = ug.UserID And ug.GroupID = g.ID and u.WindowsUser like 'bancounico\" & utilizador.Text & "'", SQLData)
SQLData.Open()
Dim dtrReader As System.Data.SqlClient.SqlDataReader = cmdSelect.ExecuteReader()
If dtrReader.HasRows Then
DropDownPerfil.DataValueField = "Login"
DropDownPerfil.DataTextField = "Description"
DropDownPerfil.DataSource = dtrReader
DropDownPerfil.DataBind()
End If
SQLData.Close()
Return True
End Function
.aspx
<asp:DropDownList ID="DropDownPerfil" runat="server"
Height="16px" Width="202px" CssClass="DropBorderColor">
</asp:DropDownList>
try the following code:
Protected Sub DropDownPerfil_SelectedIndexChanged(sender As Object, e As EventArgs)
lbperfil2.Text = DropDownPerfil.SelectedItem.Text
lbnome.Text = DropDownPerfil.SelectedValue
End Sub
The problem is that you are trying to get the value "too early". The value is not valid in the Page_Load, since the control's OnLoad event fired after the Page's OnLoad (Page_Load) event.
The way, what the others wrote the correct, since the Event handlig section (inclueding control's onchanged event) will process after the Load section.
For more details check the offical ASP.NET life cycle site in the MSDN
The likely reason is that some (if not all) the values you are assigning to the DropDownList for Login are occur more than once.
When you then select an item in the DDL, if the value of that item occurs more than once, the selected index will highlight the first instance. To test this, comment out DropDownPerfil.DataValueField = "Login"
I am sure upon selection, it will highlight the correct item you intended on selecting.
I am dynamically adding a link button to every cell in a gridview. Adding the button works however the firing of the even handler doesn't. i need the linkbutton to call a function and pass some data for processing. My code is below. I have found solutions from the site that have gotten me this far.
At the moment the gridview loads the cells with buttons in blue. when you click them they go back to plain text and no function is called.
Private Sub gv_datasource_options_RowDataBound(sender As Object, e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gv_datasource_options.RowDataBound
Try
If e.Row.RowType = DataControlRowType.DataRow Then
For Each c As TableCell In e.Row.Cells
If Len(c.Text) > 0 And c.Text <> " " Then
Dim v_lb As New LinkButton()
v_lb.Text = c.Text
AddHandler v_lb.Click, AddressOf add_datasource
v_lb.Attributes.Add("AutoPostback", "True")
v_lb.Attributes.Add("runat", "Server")
v_lb.Attributes.Add("AutoEventWireup", "True")
v_lb.CommandName = "NumClick"
v_lb.CommandArgument = e.Row.Cells(0).ToString & "|" & gv_datasource_options.HeaderRow.Cells(e.Row.Cells.GetCellIndex(c)).Text
c.Controls.Add(v_lb)
Dim sm As ScriptManager = ScriptManager.GetCurrent(Me)
sm.RegisterAsyncPostBackControl(v_lb)
End If
Next
End If
Catch ex As Exception
cl_Error.cl_Erorr.LogError(ex, txt_userid.Value, ex.ToString)
End Try
End Sub
Private Sub add_datasource(sender As Object, e As CommandEventArgs)
Try
hf_datasource_id.Value = Left(e.CommandArgument.ToString(), (Len(e.CommandArgument.ToString) - InStr(e.CommandArgument.ToString, "|")))
hf_datasource_column.Value = Left(e.CommandArgument.ToString(), (Len(e.CommandArgument.ToString) - InStr(e.CommandArgument.ToString, "|")))
hf_datasource_tableid.Value = tv_content.SelectedValue
p_datasource.Visible = False
Catch ex As Exception
cl_Error.cl_Erorr.LogError(ex, txt_userid.Value, ex.ToString)
End Try
End Sub
Rather than adding Event ("add_datasource") to Linkbutton, trying using GridView's RowCommand Event. You will surely be able to fetch the event bubbled by linkbutton on Gridview's Row Command Event (along with the commandname and commandarguments)
I have nested repeaters, each item in the nested repeater has a label and a button on it, i want to beable to access the label.text when the button is clicked, I think i'm nearly there as I can return the index of the repeater and nested repeater that is clicked, i'm just having some trouble finding the label itself.
You might be able to help me without me posting the repeater code. Here is my code behind for when the button is clicked.
Protected Sub btnEditUser_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim btnEditUser As Button = DirectCast(sender, Button)
Dim reClient As RepeaterItem = DirectCast(btnEditUser.NamingContainer.Parent.Parent, RepeaterItem)
Dim reUser As RepeaterItem = DirectCast(btnEditUser.NamingContainer, RepeaterItem)
Dim selectedClient As Integer = reClient.ItemIndex
Dim selectedUser As Integer = reUser.ItemIndex
Dim UserId As Label = DirectCast(reClients.Items(selectedClient).FindControl("lUserName"), Label)
Response.Write(selectedClient & " " & selectedUser & " " & UserId.Text)
End Sub
I'm currently getting this error 'Object reference not set to an instance of an object.' when trying to write the value of UserId.Text so i think i've got it slightly wrong in this line:
Dim UserId As Label = DirectCast(reClients.Items(selectedClient).FindControl("lUserName"), Label)
This is just a guess, but sometimes you get errors like this when not all rows contain the control you're looking for. Often the code loops through the rows in order, hits a header row first that doesn't contain the relevant control, and fails.
Here is a good MSDN article - Locating a Control Inside a Hierarchy of Naming containers.
Private Function FindControlRecursive(
ByVal rootControl As Control, ByVal controlID As String) As Control
If rootControl.ID = controlID Then
Return rootControl
End If
For Each controlToSearch As Control In rootControl.Controls
Dim controlToReturn As Control =
FindControlRecursive(controlToSearch, controlID)
If controlToReturn IsNot Nothing Then
Return controlToReturn
End If
Next
Return Nothing
End Function
Try it,
Dim UserId As Label =DirectCast(FindControlRecursive(repClient,"lUserName"),Label)
The code below displays a thumbnail of each image in a specific server directory and when I click on the image it pops up a nice full sized picture. It works perfectly.
I would however, like to be able to delete an image. I first thought I could have a button at the bottom of the page with a checkbox next to each image, giving it a uniqueID as per the filename but as they are dynamically created I couldn’t figure how to handle the Click Event on the button for a randomly named Checkbox ID. Then I tried adding a button next to each item and then tried an OnClick & OnServerClick to call a Sub but this didn’t work either.
Any/All suggestions welcomed :)
Private Sub ImageList()
If Directory.Exists(Server.MapPath("JobImages\" & DBC_JOB_JobID.Text)) Then
Dim MySB As New StringBuilder
Dim dirInfo As New DirectoryInfo(Server.MapPath("JobImages\" & DBC_JOB_JobID.Text))
MySB.Append("<ul class=""clearfix"">")
MySB.AppendLine()
For Each File In dirInfo.GetFiles()
MySB.Append("<li><a rel=""jobpic"" href=""JobImages\" & DBC_JOB_JobID.Text & "\" & File.Name & """><img src=""JobImages\" & DBC_JOB_JobID.Text & "\Thumbs\" & File.Name & """ width=""150"" height=""100"" /> <span class=""size"">" & File.Name & " </span></a></li>")
MySB.AppendLine()
Next
MySB.Append("</ul>")
MySB.AppendLine()
lblMyPictures.Text = MySB.ToString
End If
End Sub
OK what Kendrick is talking about (basically) is using server side controls to keep track of which file to delete. What you are doing right now is dumping markup into a Label control, which on postback won't fire an event on the server side. However you can accomplish this easily with server side controls.
The basic idea is you use a container control such as a Panel and add each child control to it. Then you hook events to each row with data identifying that row (such as filename).
Markup:
<asp:Panel ID="pnlList" runat="server">
</asp:Panel>
Code-Behind:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Directory.Exists(Server.MapPath("Files")) Then
Dim objDirInfo As New DirectoryInfo(Server.MapPath("Files"))
For Each objFile As FileInfo In objDirInfo.GetFiles()
Dim objLabel As New Label
objLabel.Text = objFile.Name
Dim objLinkButton As New LinkButton
objLinkButton.Text = "Delete"
objLinkButton.CommandName = "Delete"
objLinkButton.CommandArgument = objFile.Name
AddHandler objLinkButton.Command, AddressOf DeleteFile
Dim objLiteral As New LiteralControl
objLiteral.Text = "<br/>"
pnlList.Controls.Add(objLabel)
pnlList.Controls.Add(objLinkButton)
pnlList.Controls.Add(objLiteral)
Next
End If
End Sub
Public Sub DeleteFile(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.CommandEventArgs)
If e.CommandName = "Delete" Then
Dim strFileName As String = Server.MapPath("Files\" & e.CommandArgument)
If File.Exists(strFileName) Then
Dim objFile As New FileInfo(strFileName)
objFile.Delete()
End If
End If
End Sub
This would be an excellent example of where using a data aware would make your life a lot easier.
That said, if you didn't want to use a server-side control, you could assign an ID to each checkbox (i.e. DeleteImage_1) and then store the ID and associated image name in the viewstate on the page. Go through the checked checkboxes and refer back to the viewstate for the name that goes with each ID when they click the delete button.