ASP.NET: неправильное событие запускается, когда я нажимаю LinkButton

У меня есть "корзина" Repeater, где у каждого элемента есть пара элементов управления. Мы сосредоточимся на двух DropDownLists, LinkButton и TextBox. Списки находятся в одной группе проверки, а кнопка и текстовое поле - в другой.

Оба списка имеют обработчик событий OnSelectedIndexChanged, который выполняет некоторые вычисления на основе выбора в обоих списках DropDownLists. В обоих списках также есть AutoPostBack="True".

Кнопка имеет обработчик OnClick, который также выполняет некоторые вычисления в соответствии с числом в текстовом поле.

Мне нужно, чтобы расчеты обновлялись немедленно, поэтому я добавил еще одну привязку данных для Repeater - для каждого обработчика событий.

Проблема в том, что я не могу получить значение из TextBox после того, как нажму на один из DropDownLists. Он всегда равен 1. В фоновом режиме обработчик событий OnSelectedIndexChanged срабатывает сначала, а OnClick кнопок срабатывает после него. Это происходит только после того, как я изменяю один из списков, и с этого момента это происходит каждый раз, когда я нажимаю эту кнопку. До этого - все нормально на всех элементах управления.

Что вы думаете? Ниже приведен код (надеюсь, его не слишком много, я включил все, что принимает участие) - Большое спасибо!

Вот шаблон повторителя:

                <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>

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

Вот обработчик события DropDownLists:

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

И, наконец, обработчик LinkButton OnClick:

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

Спасибо :)


person pilau    schedule 09.05.2012    source источник


Ответы (2)


Я нашел решение!

По-видимому, это происходит из-за ограничения состояния представления в ASP.NET, из-за которого OnSelectedIndexChanged срабатывает при Page_Load независимо от того, действительно ли пользователь выбрал другое значение.

Поэтому, когда срабатывает обработчик события, я проверяю, вызвал ли меня DropDownLists или другой элемент управления, который предотвращает запуск события, когда в этом нет необходимости, и сохраняет всю обработку событий на странице нетронутой:

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
person pilau    schedule 10.05.2012

Я знаю, что на этот вопрос уже был дан ответ, но у меня была очень похожая проблема с совершенно другим решением, и, поскольку это первое сообщение, появившееся в Google, я решил добавить его сюда.

У меня была кнопка ссылки, и при нажатии на нее, но только в IE9, она активировала другую кнопку на странице и вызывала ее событие, а не свое собственное.

После долгих возни и гугления я понял, что не только моя кнопка активировала другую кнопку, но и если я щелкнул где-нибудь в определенном разделе моей страницы.

В конце концов я обнаружил проблему после полного удаления моей страницы. Это было так:

   <label style="width: 100%" />

пустой тег label. После удаления все было нормально.

person Bex    schedule 02.10.2012