ASPX Webform Linkbutton in user control does not trigger click event - asp.net

I've read tons of posts with the same kind of issue, I studied a lot of solutions but I still can't solve my problem.
I have a master page and a default.aspx nesting a user control.
default.aspx :
<%# Register TagPrefix="uc" TagName="MenuSideUserControl" Src="~/Controls/MenuSide.ascx" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<div class="row">
</div>
<div class="row">
<div id="sideMenu">
<uc:MenuSideUserControl runat="server" ID="wkfMenuSide">
</uc:MenuSideUserControl>
</div>
<div id="remoteContent">
</div>
</div>
</asp:Content>
default.aspx.vb :
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
AddHandler wkfMenuSide.UserControlLinkClick, AddressOf MenuSide_UserControlLinkClick
End Sub
Protected Sub MenuSide_UserControlLinkClick(sender As Object, e As EventArgs)
Dim parentId = CType(sender, LinkButton).CommandArgument
_menuSide.BuildSideMenu(_dao.GetMenuItems(_userID, parentId))
End Sub
MenuSide.ascx :
<%# Control Language="vb" AutoEventWireup="false" CodeBehind="MenuSide.ascx.vb" Inherits="IntranetWKF.MenuSide" %>
<div class="col-sm-2" style="padding-left: 0;">
<div runat="server" class="panel-group" id="accordion" ClientIDMode="Static">
</div>
</div>
MenuSide.ascx.vb
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
BuildSideMenu(_dao.GetMenuItems(0, 3))
End Sub
Public Sub BuildSideMenu(sideMenuItems As IList(Of WkfMenuItem))
Dim pnlDefault As HtmlGenericControl
Dim pnlHeading As HtmlGenericControl
Dim pnlTitle As HtmlGenericControl
Dim linklist As HtmlGenericControl
Dim link As LinkButton
Dim lastRegroupement = String.Empty
For Each m As WkfMenuItem In sideMenuItems
pnlDefault = New HtmlGenericControl
With pnlDefault
.TagName = "div"
.Attributes("class") = "panel panel-default"
End With
[...]
link = New LinkButton
With link
.Text = m.libelle
End With
If Not String.IsNullOrEmpty(m.url) Then : link.PostBackUrl = m.url
Else
With link
.CommandArgument = m.id
.CommandName = "parentId"
.ClientIDMode = ClientIDMode.Static
.Attributes("data-parentid") = m.id
End With
AddHandler link.Click, AddressOf LinkButtonClicked
End If
pnlTitle.Controls.Add(link)
pnlHeading.Controls.Add(pnlTitle)
pnlDefault.Controls.Add(pnlHeading)
accordion.Controls.Add(pnlDefault)
End If
Next
End Sub
Public Event UserControlLinkClick As EventHandler
Protected Sub LinkButtonClicked(sender As Object, e As EventArgs)
RaiseEvent UserControlLinkClick(Me, e)
End Sub
I use an event and a delegate and bind the delegate to the LinkButton.
In the default.aspx Page_Load (I tried in the OnInit event too) I bind a click handling method that is never triggered, this is where I turn around without a solution.
Those LinkButton has to rebuild the menu they're nesting in on click.
The goal at end is to update the menus and content ajax likely.

Related

ASPX Webform - Programmatically created linkbutton never trigger event in UpdatePanel

I have a simple test app with a MasterPage, a Default.aspx page containing an UpdatePanel with few html and asp controls.
My purpose is to create dynamically controls and bind events.
I know the issue about IDs on controls and binding event handlers, as the the fact that you need to register an asynccontrol to the scriptmanager.
I tried many things but my dynamically created linkbutton goes in PostBack, in the MasterPage on_load but NEVER in my attached click event.
Extra infos : the declarative asp button triggers its click event after Default.aspx Page_Load and performing a Postback, the LinkButton dynamically created goes as well in the Default Page_Load but never trigger btnTest_Click2. This app is on .NET 4.5 (Visual Studio 2015).
Any idea ?
Thx.
Default.aspx :
<%# Page Title="Home Page" Language="VB" MasterPageFile="~/Site.Master" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="TestUpdatePanel._Default" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<h1>This will never change !</h1>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Button runat="server" ID="btnTest" CssClass="btn btn-success" OnClick="btnTest_Click" Text="Hit me hard !" />
<div runat="server" id="testDiv">
<p>Hello this a test</p>
</div>
</ContentTemplate>
<Triggers>
</Triggers>
</asp:UpdatePanel>
</asp:Content>
Default.aspx.vb code-behind :
Public Class _Default
Inherits Page
Dim currentsm As ScriptManager
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
currentsm = CType(Page.Master.FindControl("sm1"), ScriptManager)
If Not IsPostBack Then
MsgBox("It's not a postback", MsgBoxStyle.DefaultButton1)
Else
MsgBox("It's a Postback !", MsgBoxStyle.DefaultButton1)
End If
End Sub
Protected Sub btnTest_Click(sender As Object, e As EventArgs)
BuildButton()
End Sub
Private Sub BuildButton()
Dim link = New LinkButton
link.ID = "linkTest"
link.ClientIDMode = ClientIDMode.Static
link.Text = "This is a new Ajax link :-)"
AddHandler link.Click, AddressOf btnTest_Click2
Dim trigger As AsyncPostBackTrigger = New AsyncPostBackTrigger
trigger.ControlID = link.ClientID
trigger.EventName = "Click"
UpdatePanel1.Triggers.Add(trigger)
currentsm.RegisterAsyncPostBackControl(link)
testDiv.Controls.Add(link)
UpdatePanel1.Update()
End Sub
Private Sub BuildDiv()
Dim divToCreate = New HtmlGenericControl
divToCreate.TagName = "div"
divToCreate.ID = "newDiv"
divToCreate.ClientIDMode = ClientIDMode.Static
divToCreate.Attributes("class") = ("btn btn-alert")
divToCreate.InnerText = "It works !"
testDiv.Controls.Add(divToCreate)
UpdatePanel1.Update()
End Sub
Protected Sub btnTest_Click2(sender As Object, e As EventArgs)
BuildDiv()
End Sub
I finally got it with the use of the OnInit event to instanciate the dynamically created controls like this :
Protected Overrides Sub OnInit(e As EventArgs)
MyBase.OnInit(e)
If IsPostBack Then
currentsm = CType(Page.Master.FindControl("sm1"), ScriptManager)
Dim sender = Request.Form("__EVENTTARGET").ToString
If sender.Contains("btnTest") Then
BuildButton()
ElseIf sender.Contains("linkTest") Then
BuildDiv()
End If
End If
End Sub

ItemCommand on nested Repeater

I have a simple aspx page which contains 2 nested repeaters. Each of these have buttons on them. When the user clicks on a button on the outer repeater, I can capture the ItemCommand in my codebehind, however when the user clicks on an inner one, I cannot capture it.
I have read in other threads about needing to attach the event manually to the inner repeater, but cannot work this out.
Can anyone help?
Here is the aspx. I'm using vb.net code behind
<asp:Repeater runat="server" ID="ParentRepeater">
<ItemTemplate>
<li id="P<%#DataBinder.Eval(Container, "DataItem.id")%>">
<%#DataBinder.Eval(Container, "DataItem.name")%>
<asp:Button runat="server" ID="adedit" Text="Edit" CommandName='<%#DataBinder.Eval(Container, "DataItem.id")%>'
class="pages-edit" />
<asp:Button runat="server" ID="addel" Text="Delete" CommandName='<%#DataBinder.Eval(Container, "DataItem.xid")%>'
class="pages-delete" />
<ul class="page-section sub innerdrag">
<asp:Repeater runat="server" ID="childrepeater">
<ItemTemplate>
<li id="<%#DataBinder.Eval(Container, "DataItem.id")%>,">
<%#DataBinder.Eval(Container, "DataItem.name")%><asp:Button runat="server" ID="ad_edit"
Text="Edit" CommandName='<%#DataBinder.Eval(Container, "DataItem.id")%>' class="pages-edit" />
<asp:Button runat="server" ID="ad_del" Text="Delete" CommandName='<%#DataBinder.Eval(Container, "DataItem.xid")%>'
class="pages-delete" />
</li>
</ItemTemplate>
</asp:Repeater>
</ul>
</li>
</ItemTemplate>
</asp:Repeater>
Still not firing so I've put the updated VB here too
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
Dim DBFunctions As New DBFunctions.Functions
Dim dstmp As New DataSet
Dim dstmp2 As New DataSet
dstmp = DBFunctions.SQLDataSet("SELECT id,name, 'x'+cast(id as varchar(50)) as xid from pages where parent = 0 and coalesce(active,1)=1 order by orderby asc", "data")
dstmp2 = DBFunctions.SQLDataSet("SELECT id,name , 'x'+cast(id as varchar(50)) as xid,parent from pages where parent >0 and coalesce(active,1)=1 order by orderby asc", "data2")
Dim allData As New DataSet
allData.Tables.Add(dstmp.Tables(0).Copy)
allData.Tables.Add(dstmp2.Tables(0).Copy)
allData.Relations.Add(New DataRelation("Children", allData.Tables(0).Columns("ID"), allData.Tables(1).Columns("parent")))
ParentRepeater.DataSource = allData
ParentRepeater.DataBind()
sdhfunctions.Close()
End If
End Sub
Protected Sub repMenu1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles ParentRepeater.ItemDataBound
Dim dv As DataRowView = TryCast(e.Item.DataItem, DataRowView)
If dv IsNot Nothing Then
Dim repSubMenu As Repeater = TryCast(e.Item.FindControl("childrepeater"), Repeater)
If repSubMenu IsNot Nothing Then
AddHandler repSubMenu.ItemCommand, AddressOf childrepeater_ItemCommand
repSubMenu.DataSource = dv.CreateChildView("Children")
repSubMenu.DataBind()
End If
End If
End Sub
Protected Sub ParentRepeater_ItemCreated(ByVal sender As Object, ByVal e As RepeaterItemEventArgs) Handles ParentRepeater.ItemCreated
Dim dv As DataRowView = TryCast(e.Item.DataItem, DataRowView)
If dv IsNot Nothing Then
Dim repSubMenu As Repeater = TryCast(e.Item.FindControl("childrepeater"), Repeater)
If repSubMenu IsNot Nothing Then
AddHandler repSubMenu.ItemCommand, AddressOf childrepeater_ItemCommand
repSubMenu.DataSource = dv.CreateChildView("Children")
repSubMenu.DataBind()
End If
End If
End Sub
Protected Sub childrepeater_ItemCommand(ByVal source As Object, ByVal e As RepeaterCommandEventArgs)
Dim stophere As String = ""
End Sub
I put a breakpoint on stophere, and it never gets hit.
Sorry guys, I'm really confused :(
Try this:
Protected Sub ParentRepeater_ItemCreated(ByVal sender As Object, ByVal e As RepeaterItemEventArgs) Handles ParentRepeater.ItemCreated
Dim childRepeater As Repeater = DirectCast(e.Item.FindControl("childrepeater"), Repeater)
AddHandler childRepeater.ItemCommand, AddressOf childrepeater_ItemCommand
childRepeater.DataSource = "the data source for childRepeater"
childRepeater.DataBind()
End Sub
Protected Sub childrepeater_ItemCommand(ByVal source As Object, ByVal e As RepeaterCommandEventArgs)
End Sub

Adding .net RadioButtonsList control dynamically in code file, no SelectedValue in Post Back

I am having trouble getting the SelectedValue from a RadionButtonsList that I'm creating dynmically in a code file. I'm adding it to a PlaceHolder control on the aspx page. After PostBack the radio button keeps its selection on the page, but I am not able to get the value from within the code file.
I understand I can create the RadioButtonsList in the HTML page, but I need to understand how to accomplish this from only the code file. The real problem I'm having is more complicated. (Creating dynamic number of true/false RadioButtonsList controls)
quiz.aspx
<%# Page Title="Quiz" MasterPageFile="~/MasterPage.master" Language="VB" CodeFile="quiz.aspx.vb" Inherits="quiz" %>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<asp:PlaceHolder ID="testholder" runat="server"></asp:PlaceHolder>
<asp:Button ID="lblNext" runat="server" type="submit" Text="Next" accesskey="n"/>
</asp:Content>
MasterPage.master
<%# Master Language="VB" CodeFile="MasterPage.master.vb" Inherits="MasterPage" %>
quiz.aspx.vp
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim testlist As New RadioButtonList
testlist.Items.Add(New ListItem("test 1", "test1"))
testlist.Items.Add(New ListItem("test 2", "test2"))
testholder.Controls.Add(testlist)
If (IsPostBack) Then
Debug.WriteLine("testlist: " & testlist.SelectedValue)
End If
End Sub
My output after submit is: "testlist: ". Any ideas?
You have to load the controls before page_load event is triggered so that loadpostbackdata will get a chance to load the viewstate of the dynamic controls.
I am able to see the selected value after moving the dynamic controls to page_init event.
Dim testlist As New RadioButtonList
Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs)
{
testlist.Items.Add(new ListItem("test1", "test1"))
testlist.Items.Add(new ListItem("test2", "test2"))
testholder.Controls.Add(testlist)
}
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
{
If (IsPostBack) Then
Debug.WriteLine(testlist.SelectedValue)
End If
}

Calendar Controls, Event Handler for Load Event

I have been working on this for quite a while now. My code will show all the different ways and things that I have tried to get the problem fixed, but with no luck...so far. What I need to do is:
Start an event handler for the Load event of the form. Then add code to display the current date in the format shown above if the form is not being posted back.
Add a calendar control to the next paragraph, and set its Visible property to False so it's hidden when the form is first displayed.
Code an event handler for the Click event of the image button. This shold hide the image button and display the calendar control.
Code an event handler for the SelectionChanged event of the calendar control. This should get the selected date and display it in the text box with today's date and should also hide the calendar control and display the image button.
I hope that someone can help me sort out what I am doing wrong and help me get to the correct solution. Not really happy with the outcome so far.
My code-behind:
Partial Class Request
Inherits Page
Dim ImageButton1 As ImageButton1
Protected Sub Calendar_SelectionChanged(object sender, EventArgs e)
Label.Text = "Current date: " + System.DateTime.Now.ToLongDateString()
Label.Text = "Selected date: " + Calendar.SelectedDate.ToLongDateString()
Dim label1 = System.DateTime.Now
Dim label2 = SelectedDate
Dim ImageButton1 = ImageButton1
End Sub
protected void Calendar_SelectionChanged(object sender, EventArgs e)
{
lblday.Text = Calendar1.TodaysDate.ToShortDateString();
lblbday.Text = Calendar1.SelectedDate.ToShortDateString();
}
' Display using current (en-us) culture's short date format
Dim ddlDate As Date = #3/15/2008#
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
Calendar.SelectedDate = DateTime.Now;
Label.Text = "Today's date and time is :" + Calendar.SelectedDate;
Calendar.SelectedDate = DateTime.Today
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
If Not IsPostBack Then
Me.clnArrival = thisDate.ToString
End If
End Sub
Sub Submit(s As Object, e As EventArgs)
TextBox1.Text = "The date and time is " & Now()
End Sub
Protected Sub ddlDay_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles ddlDay.SelectedIndexChanged
clnArrival.Visible = False
Dim day As String = ddlDay.SelectedItem.Text(ddlDay.SelectedValue)
End Sub
Protected Sub ddlMonth_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles ddlMonth.SelectedIndexChanged
Dim month As String = ddlMonth.SelectedItem.Text(ddlMonth.SelectedValue)
End Sub
Protected Sub clnArrival_SelectionChanged(ByVal sender As Object, ByVal e As EventArgs) Handles clnArrival.SelectionChanged
ddlMonth_SelectedValue = clnArrival.SelectedDate.Month.ToString
ddlDay_SelectedValue = clnArrival.SelectedDate.Day.ToString
clnArrival.Visible = True
End Sub
End Class
My markup:
<%# Page Language="VB" AutoEventWireup="false" CodeFile="Request.aspx.vb" Inherits="Request" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Chapter 6: Reservations</title>
<link href="Styles/Main.css" rel="stylesheet" type="text/css" />
<link href="Styles/Request.css" rel="stylesheet" type="text/css" />
<script language="VB" runat="server">
Sub Page_Load()
Response.Write("Today is: ")
End Sub
</script>
</head>
<body>
<form id="form1" runat="server">
<div id="page">
<h1>Royal Inn and Suites</h1>
<h2>Where you’re always treated like royalty</h2>
<p id="arrival_date">
Arrival date:
<asp:Calendar ID = "Calendar" runat = "server" SelectionMode="DayWeekMonth" OnSelectionChanged="Calendar_SelectionChanged" SelectedDate="1/1/0001" VisibleDate="1/1/0001">
<asp:ImageButton ID="ImageButton1" runat="server" AlternateText="Click to show calendar" ImageUrl="C:\aspnet4_vb\Jeanne Tatro Webs 424 - HW 6 - Ch06Reservation\Images\Calendar.bmp" />
</asp:Calendar>
</p>
<p class="clear">
Number of nights:
</p>
<p>
Number of adults:
Children:
</p>
<h3>Preferences</h3>
<p>
Room type:
</p>
<p>
Bed type:
</p>
<p id="requests">Special requests:</p>
<h3 class="clear">Contact information</h3>
<p class="contact">Name:</p>
<p class="contact">Email:</p>
<p id="buttons"></p>
<p id="message"></p>
</div>
</form>
</body>
</html>

Declarative event handling from ASP.NET user control to page

I am trying to figure out how to declaratively pass in a event handler into
a user control, but I am stumped. All I can make work is the user control's
event handler.. I can't seem to bubble up the caught event into the parent
page. Ideas would be quite welcome. Here is my code:
Default.aspx:
<%# Page Language="VB" %>
<%# Register TagPrefix="rpt" TagName="filter" Src="WebUserControl.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Test Controls</title>
</head>
<body>
<form id="form1" runat="server">
<rpt:filter ID="DataView1Filters" runat="server" SelectedIndexChanged="DropDown_SelectedIndexChanged" />
<asp:Label ID="Label1" runat="server" />
</form>
<script runat="server">
Public Sub DropDown_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
Label1.Text = String.Format("Inside declarative event handler. {0}<br>", Label1.Text)
End Sub
</script>
</body>
</html>
WebUserControl.ascx:
<%# Control Language="VB" ClassName="WebUserControlTest" %>
<asp:Panel ID="TestPanel" runat="server"></asp:Panel>
<script runat="server">
Private AllEvents As New System.ComponentModel.EventHandlerList
Public Custom Event SelectedIndexChanged As EventHandler
AddHandler(ByVal value As EventHandler)
AllEvents.AddHandler("SelectedIndexChanged", value)
End AddHandler
RemoveHandler(ByVal value As EventHandler)
AllEvents.RemoveHandler("SelectedIndexChanged", value)
End RemoveHandler
RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
Dim value As EventHandler = CType(AllEvents("SelectedIndexChanged"), EventHandler)
If Not value Is Nothing Then
value.Invoke(sender, e)
End If
End RaiseEvent
End Event
Private Sub _SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim ctrl As DropDownList = Me.FindControl("TestDropDownList")
If Not ctrl Is Nothing Then
Me.ViewState("ItemSelection") = ctrl.SelectedIndex
End If
Dim Label1 As Label = Parent.FindControl("Label1")
Label1.Text = String.Format("Inside user control event handler. {0}<br>", Label1.Text)
RaiseEvent SelectedIndexChanged(sender, e)
End Sub
Private Overloads Sub OnLoad(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
Dim ctrl As New DropDownList
With ctrl
.ID = "TestDropDownList"
.Items.Clear()
.AutoPostBack = True
AddHandler .SelectedIndexChanged, AddressOf _SelectedIndexChanged
.Items.Add(New ListItem("-- Select --", String.Empty))
.Items.Add(New ListItem("Item 1", "1"))
.Items.Add(New ListItem("Item 2", "2"))
If Not Me.ViewState("ItemSelection") Is Nothing Then
.SelectedIndex = CInt(Me.ViewState("ItemSelection"))
Else
.SelectedIndex = 0
End If
End With
TestPanel.Controls.Add(ctrl)
End Sub
</script>
Thanks!
See this previous post:
Handling User Control Events on Containing Page
Edit - added based on your comment
I should have read the question more clearly.
As far as having a UserControl raise an event that the containing page can respond to, I do not believe that this can be done declaratively.
Unless my knowledge is just lacking, the only way to accomplish this is by explicitly creating an event in the control and then handling it (by coding the event handler) on the parent page, as shown in the example I linked to.
I was recently having this same issue in C#. When you set up an event called SelectedIndexChanged asp.net will bind the attribute OnSelectedIndexChanged when using the declarative syntax.
So if you change
<rpt:filter ID="DataView1Filters" runat="server" SelectedIndexChanged="DropDown_SelectedIndexChanged" />
To
<rpt:filter ID="DataView1Filters" runat="server" OnSelectedIndexChanged="DropDown_SelectedIndexChanged" />
It should work.

Resources