VB DropDownList.SelectedIndexChanged Event Not Firing - asp.net

I have a dropdownlist that, when a specific item is selected, needs to set another dropdownlist.visible = true. Unfortunately, I cannot get the dropdownlist (or any other dropdownlist on my entire site) to fire its SelectedIndexChanged event.
Details:
This is a site that was created by my predecessor and I do not have the time to rebuild it or even upgrade it so, I really need to simply add this one feature to complete my task.
The site is written in Visual Studio .NET 2003.
Currently, no matter what I try, the SelectedIndexChanged event never fires.
I have tried the following things:
Set AutoPostBack="true"
Set AutoEventWireup="true"
Set EnableViewState="true"
Add OnSelectedIndexChanged="ddlCLSortOptions_SelectedIndexChanged" to the asp:dropdownlist object, which gives me the following error:
Compiler Error Message: BC30456: 'ddlCLSortOptions_SelectedIndexChanged' is not a member of 'ASP.reports_aspx'.
This error has led me down the path of checking any differences in the Inherits and Class name, but the only difference I found is that the class is named reports and the Inherits is ProviderLicense.reports. Of course, when I change them to match identically, that throws a completely different error.
Change the ddlCLSortOptions_SelectedIndexChanged Sub from Private to Protected, and then even to Public just for good measure.
Remove the Handles ddlCLSortOptions.SelectedIndexChanged and add the AddHandler option
I'm sure there's even more that I've tried, but I can't think of anything else.
Here is my code:
reports.aspx
<%# Page Language="vb" AutoEventWireup="true" Codebehind="reports.aspx.vb" Inherits="ProviderLicense.reports"%>
...
<asp:dropdownlist id="ddlCLSortOptions" style="POSITION: absolute; LEFT: 365px; Z-INDEX: 140; TOP: 315px" runat="server" AutoPostBack="True" Visible="False">
<asp:ListItem Value="Provider" Selected="True">Provider</asp:ListItem>
<asp:ListItem Value="RecDate">Received Date</asp:ListItem>
<asp:ListItem Value="EntDate">Entered Date</asp:ListItem>
<asp:ListItem Value="DateComp">Date Completed</asp:ListItem>
<asp:ListItem Value="LicType">License Type</asp:ListItem>
<asp:ListItem Value="Investigator">Investigator</asp:ListItem>
<asp:ListItem Value="Worker">Worker</asp:ListItem>
<asp:ListItem Value="Disposition">Disposition</asp:ListItem>
</asp:dropdownlist>
reports.aspx.vb
Public Class reports
Inherits System.Web.UI.Page
Protected WithEvents ddlCLSortOptions As System.Web.UI.WebControls.DropDownList
...
Private Sub ddlCLSortOptions_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ddlCLSortOptions.SelectedIndexChanged
Label2.Text = "IT WORKED!" 'Just to see if the event fires
If ddlCLSortOptions.SelectedValue = "Disposition" Then
lblDisposition.Visible = True
ddlDisposition.Visible = True
Else
lblDisposition.Visible = False
ddlDisposition.Visible = False
End If
End Sub
I hope it's something simple that I've just missed, but I'm open to trying just about anything now.

have you tried this?
set AutoEventWireUp="false" in reports.aspx
set the OnSelectedIndexChanged="ddlCLSortOptions" in the DropDownList tag in reports.aspx
change Private Sub to Protected Sub on the OnSelectedIndexChanged event in reports.aspx.vb

Related

Dropdown in listview SelectedIndexChanged doesn't work first time but does after

I've searched high and low, I can't seem to find out what's happening with this. I've simplified the code, but I really have taken it back to as basic as this and still have the same problem.
I have a drop down list in a a repeater (in a Web Form with master page):
<asp:DropDownList ID="TicketQuantityDDL" runat="server" CssClass="qtyddl" AutoPostBack="true" OnSelectedIndexChanged="TicketQuantityDDL_SelectedIndexChanged" CausesValidation="false" SelectedIndex='<%# CInt(Eval("Quantity")) - 1%>'>
<asp:ListItem Value="1">1</asp:ListItem>
<asp:ListItem Value="2">2</asp:ListItem>
<asp:ListItem Value="3">3</asp:ListItem>
<asp:ListItem Value="4">4</asp:ListItem>
<asp:ListItem Value="5">5</asp:ListItem>
<asp:ListItem Value="6">6</asp:ListItem>
</asp:DropDownList>
Handler
Protected Sub TicketQuantityDDL_SelectedIndexChanged(sender As Object, e As EventArgs)
myLiteral.text = "Selected Index Changed handled..."
End Sub
The first time the page is loaded if I change the DDL the the page is posted back - the selected index change handler is NOT fired (I've stepped through the code, page.ispostback is true). Every time after the handler works unless the page is full reloaded.
Things I've tried:
Manually adding a handler OnItemCreated
Manually adding a handler OnItemDataBound
Manually registering the control for async postback with scriptmanager
Using OnClientSelectedIndexChanged to trigger postback from the client
Removing AutoPostBack and all of the above again...
I've used Page.Request.Params("__EVENTTARGET") to verify that when the partial postback is fired that the control is the drop down.
Even though viewstate is enabled I've tried specifying this for the control and the page directly.
Disabling validation.
I've tried not binding the value of the drop down and just leaving it
as is with no selected value and then manually setting the initial
selected value - no dice.
Tried removing update panel, same issue.
Things that are DEFINITELY not happening here.
I'm not rebinding on post back if not page.ispostback... databind...
I'm not selecting the same value/first item in the drop down
This isn't an auto ID problem, the controls ID stay the same through postbacks.
I'm not doing anything funky other than binding the repeater to a list of objects.
Why isn't the handler firing the first time? After the first time everything works exactly as intended.
Update
I've replicated the exact same behaviour in a list view. Due to time constraints I've used another approach but I'd really like to know how to fix this or at least know why it doesn't work.
Update 2
I've tested the functionality with a bog standard web form and it functions correctly. Something is up with this being in a contentplaceholder from a masterpage, the script manager or update panel. It's as if the event handler for the dropdown is only registered after the first post back, I've tried registering the handler in DataBound and also in the page LoadComplete events, the same thing still happens.
Update 3
I've since changed it to a list view, I'm having the exact same issue though.
This is on a web form with master page, the master page contains the script manager, the list view is in an update panel, although I've tried removing this and I still have the same issue. I've not included the onselectedindexchanged code, I've made it as simple as changing the text of a literal - doesn't work first post back, does the second.
I had originally specified the list items manually but have changed this to programatically at itemDataBound, still no difference.
As I stated above when I check which control caused the postback it's definitely the ddl, it just doesn't fire selectindexchanged the first time. I've also tried specifying the OnSelectedIndexChange in the control itself, still no dice.
Page load ,bind, list view and on item created code.
Page Load
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
Dim _Basket = SessionHandler.getSessionObject(SessionHandler.SessionObjects.Basket)
If _Basket Is Nothing OrElse DirectCast(_Basket, BasketContainer).BasketItemList.Count = 0 Then
BasketSectionContainer.Visible = False
alertLiteral.Text = AlertGenerator.GetAlertHTML("No Items in Basket", "There are no items in your basket, please use the menu above to navigate the site.", AlertGenerator.AlertType.warning)
If _Basket IsNot Nothing Then SessionHandler.removeSessionObject(SessionHandler.SessionObjects.Basket)
Exit Sub
Else
Dim lBasket = DirectCast(_Basket, BasketContainer)
BindBasket(lBasket)
End If
End If
End Sub
Bind
Private Sub BindBasket(lBasket As BasketContainer)
basketListView.DataSource = lBasket.BasketItems
basketListView.DataBind()
bindTotals(lBasket) 'This just sets text of literals on the page outside of the listview
If lBasket.Postage Then
PostageDDL.visible = True 'This is outside of the list view also
End If
End Sub
Item Created
Private Sub basketListView_ItemCreated(sender As Object, e As ListViewItemEventArgs) Handles basketListView.ItemCreated
Dim QtyDDL As DropDownList = DirectCast(e.Item.FindControl("TicketQuantityDDL"), DropDownList)
AddHandler QtyDDL.SelectedIndexChanged, AddressOf TicketQuantityDDL_SelectedIndexChanged
End Sub
_Item Data Bound _
Private Sub basketListView_ItemDataBound(sender As Object, e As ListViewItemEventArgs) Handles basketListView.ItemDataBound
Dim data As BasketItem = DirectCast(e.Item.DataItem, BasketItem)
Dim QtyDDL As DropDownList = DirectCast(e.Item.FindControl("TicketQuantityDDL"), DropDownList)
For i As Integer = 1 To 6
QtyDDL.Items.Add(New ListItem(i.ToString, i.ToString))
Next
QtyDDL.DataTextField = data.BasketItemID.ToString 'no command arg for DDL so using this, I've tested without, doesn't make a difference.
Select Case data.BasketType
Case BasketInfo.BasketItemType.DiscountedTickets, BasketInfo.BasketItemType.Tickets, BasketInfo.BasketItemType.Goods
'tickets and goods...
QtyDDL.Items.FindByValue(data.Quantity.ToString).Selected = True
Case Else
'non ticket or goods type, disable quantity selection
QtyDDL.Items.FindByValue("1").Selected = True
QtyDDL.Enabled = False
End Select
End Sub
_List View _
<asp:ListView ID="basketListView" runat="server">
<LayoutTemplate>
<table class="cart-table responsive-table">
<tr>
<th>Item</th>
<th>Description</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
<th></th>
</tr>
<asp:PlaceHolder ID="itemPlaceholder" runat="server" />
</table>
<table class="cart-table bottom">
<tr>
<th>
<asp:Button ID="ApplyDiscountCodeButton" runat="server" CssClass="button color pull-right" Text="Apply Code" />
<asp:TextBox ID="DiscountCodeTextBox" runat="server" CssClass="discount-tb pull-right" />
</th>
</tr>
</table>
<div class="clearfix"></div>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td>
<img src="/images/shows/<%# Eval("imageURL")%>.jpg" alt="<%#Eval("BasketItemTitle")%>" class="basketimg" /></td>
<td class="cart-title">
<%#Eval("BasketItemTitle")%>
<br />
<%# String.Format("{0:dddd} {1} {0:MMMM yyyy} | {0:HH:mm}", Eval("PerformanceStarts"), Eval("OrdinalDay"))%>
<br />
<%# Eval("VenueTitle")%>
</td>
<td>
<%#Eval("PriceBandType")%>
<br />
# <%# String.Format("{0:c}", Eval("PriceBandValue"))%>
</td>
<td>
<asp:DropDownList ID="TicketQuantityDDL" runat="server" CssClass="qtyddl" AutoPostBack="true" ClientIDMode="Static" />
</td>
<td class="cart-total"><%#String.Format("{0:c}", Eval("BasketItemTotalValue"))%></td>
<td>
<asp:LinkButton ID="RemoveLinkBtn" runat="server" CssClass="cart-remove" CommandName="RemoveBasketItem" CommandArgument='<%#Eval("BasketItemID")%>' />
</td>
</tr>
</ItemTemplate>
</asp:ListView>
Since the Dropdown in inside the repeater, you can try the following Option instead.
Add OnItemCommand to the repeater. This should definitely Trigger the Event on selection Change in the Dropdown. Then in the OnItemCommand you Need to cast the Sender to DropDownList to be able get the selected value of the dropdown
You have to register the dropdown list event like this.
protected virtual void OnRepeaterItemCreated(object sender, RepeaterItemEventArgs e)
{
DropDownList dropdown = (DropDownList)e.Item.FindControl("TicketQuantityDDL");
dropdown.SelectedIndexChanged += TicketQuantityDDL_SelectedIndexChanged;
}
And also add this piece of code in your repeater.
OnItemCreated="OnRepeaterItemCreated"
And then you can do the selected index changed event like this.
protected void TicketQuantityDDL_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList mydropdownlist = (DropDownList)sender;
Response.Write(mydropdownlist.SelectedValue);
}
protected void dropdownlist1_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList ddlListFind = (DropDownList)sender;
ListViewItem item1 = (ListViewItem)ddlListFind.NamingContainer;
DropDownList getDDLList = (DropDownList)item1.FindControl("dropdownlist1");
Label lblMessage = (Label)item1.FindControl("lblMsg");
lblMessage.Visible = true; lblMessage.Text = "dropDown text is : " + getDDLList.SelectedItem.Text + " and value is : " + getDDLList.SelectedItem.Value;
}

Asp.net webforms - CausesValidation=true is being ignored

I have encountered a problem with a page we have, and have narrowed down a sample like so:
ASPX:
<div>
<asp:DropDownList ID="ddlSomething" runat="server"
CausesValidation="true" AutoPostBack="true">
<asp:ListItem>One</asp:ListItem>
<asp:ListItem>Two</asp:ListItem>
</asp:DropDownList>
<asp:Button ID="btnFilter" runat="server" Text="Filter" />
</div>
Code:
Partial Class ValTest
Inherits System.Web.UI.Page
Protected Sub btnFilter_Click(sender As Object, e As EventArgs) Handles btnFilter.Click
BindGrid()
End Sub
Protected Sub ddlSomething_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ddlSomething.SelectedIndexChanged
BindGrid()
End Sub
Private Sub BindGrid()
If (Page.IsValid) Then
'Do something that takes a little time here
System.Threading.Thread.Sleep(2000)
Response.Write("Done")
End If
End Sub
End Class
Note that the dropdown list has autopostback set to true and causesvalidation set to true.
Now, if I change the dropdown list and let the page load, it works without issue. Similarly, if I just click the button, then it works ok. However, if I change the dropdown list and then, before the page has totally reloaded, click the button, then I get this error:
Page.IsValid cannot be called before validation has taken place. It should be queried in the event handler for a control that has CausesValidation=True and initiated the postback, or after a call to Page.Validate.
Now, I can fix this by putting a Page.Validate() in front of my check for Page.IsValid, however I am curious if anybody can explain why this is happening. I am expecting two postbacks to have been sent, each causing validation, and each should have worked...
ASP.net 4.5, just in case it makes a difference.

When does DataBinding Occur for Drop Down Lists?

Here is my drop down list and data source. My question is.. when is it possible to set a defaulted selected option for the drop down list, aka when have all the dropdownlists been databound and their ListItems populated? I have tried Page_PreRender, Page_PreRenderComplete, Page_Load.
I have read over MSDN's Page Life cycle event which suggest Page_PreRender.
<asp:DropDownList ID="ddlRampStandard" runat="server"
DataSourceID="RampStandardDataSource" DataTextField="StandardName"
DataValueField="StandardName" RepeatDirection="Horizontal"
ViewStateMode="Enabled"></asp:DropDownList>
<asp:SqlDataSource ID="RampStandardDataSource" runat="server"
ConnectionString="<%$ ConnectionStrings:AIMP_DeleteMeConnectionString %>"
SelectCommand="SELECT [StandardName] FROM [CR_Standard]"></asp:SqlDataSource>
Here's the simple code-behind which illustrates what I'm trying to do.
Protected Sub Page_PreRenderComplete(sender As Object, e As System.EventArgs) Handles Me.Load
ddllstSideOfStreet.Items(0).Selected = True
End Sub
I'm getting an instance not created error suggesting ddllstSideOfStreet has no items. I do verify that with a breakpoint and watch that there are no items in existence in any of the previously mentioned prerender, load, prerendercomplte functions.. However when the page loads, the dropdownlist does indeed load with the expected databound information. Thoughts?
just to make sure, have both the handler in the markup and the method using the correct handler in the code behind.
Like this:
Protected Sub Page_PreRender(sender As Object, e As System.EventArgs) Handles Me.PreRender
End Sub
And the markup as follows:
<asp:DropDownList ID="ddlRampStandard" runat="server"
DataSourceID="RampStandardDataSource" DataTextField="StandardName"
DataValueField="StandardName" RepeatDirection="Horizontal"
ViewStateMode="Enabled" OnPreRender="Page_PreRender"></asp:DropDownList>
Tried a similar solution on my machine a moment ago and it worked.

Pass Link-Button Click from One User Control to Another

I have two user controls on the same page. One contains a ListView that displays navigation links, the second user control should be updated when user clicks on the buttonlink in the ListView. How can I do this?
UserControl A should handle the button-click and raise a custom event declared in the UserControl
The page handles this event and calls a public method of UserControl B that updates it's content
You could pass necessary informations from UserControl A to page via EventArgs(or pass the UserControl itself as argument and use it's public properties).
The page then passes the arguments to UserControl B via method parameter or by changing it's public properties before calling the Update-Method.
http://msdn.microsoft.com/en-us/library/fb3w5b53.aspx
http://chiragrdarji.blogspot.com/2007/08/raise-event-from-user-control-to-main.html
Here is the sample code you've requested.
Sorry for the meaningless naming but you haven't told what's this all about. You should use readable variables,properties,method and event-names instead.
Reduced UserControl A with a ListView:
<%# Control Language="vb" AutoEventWireup="false" CodeBehind="UsercontrolA.ascx.vb" Inherits="WebApplication1.UserControlA" %>
<asp:ListView ID="ListView1" runat="server">
<ItemTemplate>
<asp:LinkButton ID="LinkButton1"
CommandName="LinkClick"
CommandArgument='<%#Eval("ID") %>'
runat="server"
Text='<%#Eval("Text") %>'></asp:LinkButton>
</ItemTemplate>
</asp:ListView>
Removed the ListView databinding from codebehind because that doesn't matter. The important part is handling the ListView's ItemCommand and raising the custom event:
Public Event LinkClicked(sender As UserControlA, id As Int32)
Private Sub LV_ItemCommand(sender As Object, e As ListViewCommandEventArgs) Handles ListView1.ItemCommand
If e.CommandName = "LinkClick" Then
Dim id = CType(e.CommandArgument, Int32)
' This is the best way for UC's to commmunicate with the page: '
RaiseEvent LinkClicked(Me, id)
End If
End Sub
Simple UserControl B with nothing more than a Label(ascx):
<%# Control Language="vb" AutoEventWireup="false" CodeBehind="UserControlB.ascx.vb" Inherits="WebApplication1.UserControlB" %>
<asp:Label ID="Label1" runat="server"></asp:Label>
With an Update-Method in codebehind:
Public Sub Update(showID As Int32)
Me.Label1.Text = String.Format("Link {0} clicked", showID.ToString)
End Sub
Finally, here is the Page(aspx)
<uc1:UsercontrolA ID="UC_A" runat="server" />
<br />
<uc2:UserControlB ID="UC_B" runat="server" />
It controls both UserControls. It handles the event from UserControl A and calls the Update-Method that UserControl B provides:
Private Sub LinkClicked(sender As UserControlA, id As Integer) Handles UC_A.LinkClicked
Me.UC_B.Update(id)
End Sub
The advantage of this event-approach is that UserControls stay being reusable. You can use UserControl A in other pages as well even when they don't handle this event. It's part of the controller to decide what is needed and what should be done.
UserControls as a rule should not depend on specific controllers, otherwise they are hard-linked and not reusable. That would be also a good source for nasty erros. A UserControl might be a controller for other nested (User-)Controls but not for the page itself.
Communication Summary:
Page -> UserControl -> public properties and methods
UserControl -> Page -> Events
UserControl -> UserControl -> the controller-UserControl adopts the page-role(see above)

Problem finding web control inside of Gridview TemplateField

Okay, so I'm having issues getting the value of a DropDownList that's inside of a TemplateField when updating my GridView. Originally I was using the RowCommand event to check the command name and then performing the appropriate task (update/delete), but I had problems with the event firing twice, so I switched it out for separate events (RowUpdating, RowDeleting). After doing this, FindControl is returning null every time. Just FYI, the gridview is inside of an UpdatePanel that has an AsyncPostBackTriggers for RowEditing, RowUpdating and RowDeleting events.
Here's my TemplateField inside of the GridView:
<asp:TemplateField HeaderText="Type">
<ItemTemplate>
<asp:Label
ID="lblMedTypeEdit"
Text='<%# Bind("medDesc") %>'
runat="server">
</asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList
ID="ddlMedTypeEdit"
DataSourceID="srcMedTypes"
SelectedValue='<%# Bind("medtype") %>'
runat="server"
DataTextField="medDesc"
DataValueField="medCode">
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>
Here is the code I'm using inside of
Protected Sub gvCurrentMeds_RowUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewUpdateEventArgs) Handles gvCurrentMeds.RowUpdating
Dim intRowIndex As Integer = e.RowIndex
Dim ddlMedType As DropDownList = CType(Me.gvCurrentMeds.Rows(intRowIndex).Cells(1).FindControl("ddlMedTypeEdit"),DropDownList)
End Sub
I also tried using a recursive function to find the control (below), but it is still returning back null.
Public Function FindControlRecursive(ByVal root As Control, ByVal id As String) As Control
If root.ID = id Then
Return root
End If
For Each c As Control In root.Controls
Dim t As Control = FindControlRecursive(c, id)
If Not t Is Nothing Then
Return t
End If
Next
Return Nothing
End Function
If you just want to know what the new value of the dropdown is, this is already provided for you in the NewValues property of the GridViewUpdateEventArgs object passed to the event handler.
In your example, e.NewValues["medtype"] should be the updated value.
You've already specified <%# Bind(...) %> on the dropdown, so ASP.NET will do the work of finding the controls and getting the new values for you - you don't have to plumb the control hierarchy yourself.

Resources