问题
I have a "cart" Repeater
, where every item has a couple of controls in it. The ones we're focusing on are two DropDownLists
, a LinkButton
and a TextBox
. The lists are on one validation group and the button & textbox are on another.
Both lists have an OnSelectedIndexChanged
event handler which does some calculations based on the selections in both DropDownLists
. Both lists also have AutoPostBack="True"
.
The button has an OnClick
handler which also does some calculations according to the number in the textbox.
I need the calculations to be updated immediately - so I added another data binding for the Repeater
- on each event handler
The problem is - I can't get the value from the TextBox after I click on one of the DropDownLists
. It always comes off as 1. In the background, the OnSelectedIndexChanged
event handler fires first, and the buttons' OnClick
will fires after it. That only happens after I change one of the lists - and it happens every time I click that button from that moment on. Before that - everything is normal on all controls.
What do you think? Below is some code (I hope it's not too much, I included everything that's taking part) - Thank you very much!
Here's the repeater template:
<ItemTemplate>
<tr>
<td class="size"><div><asp:DropDownList runat="server" ID="_selectSize" AutoPostBack="true" OnSelectedIndexChanged="selectChange" EnableViewState="true" TabIndex="<%#Container.ItemIndex%>" ValidationGroup="doNotValidate"></asp:DropDownList></div></td>
<td class="material"><div><asp:DropDownList runat="server" ID="_selectMaterial" AutoPostBack="true" OnSelectedIndexChanged="selectChange" EnableViewState="true" TabIndex="<%#Container.ItemIndex%>" ValidationGroup="doNotValidate"></asp:DropDownList></div></td>
<td class="quantity">
<div>
<div class="quantity_container"><asp:TextBox runat="server" ID="_txtAmount" name="quantity_<%#Container.ItemIndex%>" ValidationGroup="vCart"></asp:TextBox></div>
<div><asp:LinkButton runat="server" CssClass="refresh" id="_refreshCart" ValidationGroup="vCart"></asp:LinkButton></div>
</div>
</td>
</tr>
</ItemTemplate>
The Repeater.DataBound()
:
Protected Sub rptCart_ItemDataBound(sender As Object, e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles rptCart.ItemDataBound
If e.Item.ItemType = ListItemType.AlternatingItem OrElse e.Item.ItemType = ListItemType.Item Then
Dim OrderItem As ProxyMarket.Item = CType(e.Item.DataItem, ProxyMarket.Item)
Dim btnRemoveProduct As LinkButton = CType(e.Item.FindControl("_removeProduct"), LinkButton)
Dim btnRefreshCart As LinkButton = CType(e.Item.FindControl("_refreshCart"), LinkButton)
Dim txtAmount As TextBox = CType(e.Item.FindControl("_txtAmount"), TextBox)
Dim sizeSelect As DropDownList = CType(e.Item.FindControl("_selectSize"), DropDownList)
Dim materialSelect As DropDownList = CType(e.Item.FindControl("_selectMaterial"), DropDownList)
btnRemoveProduct.CommandName = OrderItem.ID
btnRefreshCart.CommandName = OrderItem.ID
txtAmount.Text = OrderItem.Units
AddHandler btnRemoveProduct.Click, AddressOf removeProduct
AddHandler btnRefreshCart.Click, AddressOf refreshCart
sizeSelect.DataSource = sizeList
sizeSelect.DataBind()
sizeSelect.SelectedIndex = s
materialSelect.DataSource = materialList
materialSelect.DataBind()
materialSelect.SelectedIndex = m
End If
End Sub
Here is the DropDownLists
event handler:
Protected Sub selectChange(ByVal sender As DropDownList, ByVal e As System.EventArgs)
Dim listing As New PriceListing
Dim ddl As DropDownList
Dim selectedIndex As Integer
If sender.ID = "_selectSize" Then
For Each rptrItem As RepeaterItem In rptCart.Items
ddl = CType(rptrItem.FindControl("_selectMaterial"), DropDownList)
If ddl.TabIndex = sender.TabIndex Then Exit For
Next
For Each listing In artDecoPricing
If listing.Size = sender.SelectedValue Then Exit For
Next
selectedIndex = ddl.SelectedIndex
s = sender.SelectedIndex
ElseIf sender.ID = "_selectMaterial" Then
For Each rptrItem As RepeaterItem In rptCart.Items
ddl = CType(rptrItem.FindControl("_selectSize"), DropDownList)
If ddl.TabIndex = sender.TabIndex Then Exit For
Next
For Each listing In artDecoPricing
If listing.Size = ddl.SelectedValue Then Exit For
Next
selectedIndex = sender.SelectedIndex
s = ddl.SelectedIndex
End If
Select Case selectedIndex
Case 0
Cart.Order.Items(sender.TabIndex).PriceUnit = listing.Canvas
Case 1
Cart.Order.Items(sender.TabIndex).PriceUnit = listing.Acrylic
Case 2
Cart.Order.Items(sender.TabIndex).PriceUnit = listing.Framed
Case 3
Cart.Order.Items(sender.TabIndex).PriceUnit = listing.Alucobond
End Select
Cart.SaveOrder()
s = sender.SelectedIndex
m = selectedIndex
rptCart.DataSource = Cart.Order.Items
rptCart.DataBind()
End Sub
And finally, the LinkButton
OnClick
handler:
Protected Sub refreshCart(ByVal sender As Object, ByVal e As System.EventArgs)
Dim btnRefreshCart As LinkButton = CType(sender, LinkButton)
Dim amountStr As String
Dim amount As Integer
amountStr = CType(btnRefreshCart.Parent.FindControl("_txtAmount"), TextBox).Text
If IsNumeric(amountStr) Then
amount = CDbl(amountStr)
Else
amount = -1
End If
amount = IIf(amount > 0, amount, -30)
For Each Item As ProxyMarket.Item In Cart.Order.Items
If Item.ID = btnRefreshCart.CommandName Then
Item.Units = amount
Cart.Edit_Product(btnRefreshCart.CommandName, amount)
Exit For
End If
Next
rptCart.DataSource = Cart.Order.Items
rptCart.DataBind()
End Sub
Thank you :)
回答1:
I found a solution!
Apparently this is happening because of a viewstate limitation in ASP.NET which causes the OnSelectedIndexChanged
to fire on Page_Load regardless if the user actually selected a different value.
So when the event handler fires, I am checking whether it is the DropDownLists
which called me or a different control - that prevents the event from firing when it doesn't need to - and keeps all event handling on the page intact:
Protected Sub selectChange(ByVal sender As DropDownList, ByVal e As System.EventArgs)
Dim senderClientID = Page.Request.Params.Get("__EVENTTARGET")
' Run ONLY if the relevant select control was clicked,
' otherwise this is only fired because of ASP.NET limitations,
' and will screw up the original event:
If senderClientID.IndexOf("_selectSize") <> -1 Or senderClientID.IndexOf("_selectMaterial") <> -1 Then
'do stuff
回答2:
I know this has already been answered but I was having a very similar problem, with a completely different solution and as this is the first post that appeared in google I thought I would add it here.
I had a link button and when clicking it, but only in IE9, it appeared to activate another button on the page and call it's event rather than it's own.
After much messing about and googling, I realised that it wasn't just my button that was activating the other button it was if I clicked anywhere in a particular section of my page.
I eventually found the problem after completely stripping down my page. It was this:
<label style="width: 100%" />
an empty label tag. Once deleted all was fine.
来源:https://stackoverflow.com/questions/10519714/asp-net-wrong-event-is-fired-when-i-click-a-linkbutton