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 :)
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
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.
Related
I am creating a simple guessing game. Many of the controls are repetitive, so I'd like to loop through them to databind and search for enabled or disabled controls. When I try to run the page after coding either foreach method in my code, I get an "object reference not set to an instance of an object" error.
How would I fix this without creating a new instance of my control? I've tried that already; it doesn't overwrite the existing control on my aspx page. Obviously it is creating new ones somewhere, but I'm not sure where; I don't see well. When I work on the computer I do it at 350% - 400% magnification.
Here is a sample of my aspx page:
<div class="Character">
<img src="Images/1.png" style="width: 100%;" /><br />
<asp:DropDownList ID="DDL1" runat="server" CssClass="BigText"></asp:DropDownList><br />
<asp:Button ID="BTN_SubmitGuess1" runat="server" CssClass="BigText Button2" Text="Submit Guess" />
</div>
Here is a sample of my codebehind. I have written my code for both databinding and finding enabled or disabled controls in it:
Dim arr() As String = {"One", "Two", "Three", "Four", "Five"}
Dim ddlControls() As DropDownList = {DDL1, DDL2, DDL3, DDL4, DDL5}
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
If Not IsPostBack Then
'What I have now
DDL1.DataSource = arr
DDL1.DataBind()
...
'What I'd like to have
For Each ddl As DropDownList In ddlControls
ddl.DataSource = arr
ddl.DataBind()
End If
Dim remaining As Integer
For Each ddl As DropDownList In ddlControls
If ddl.Enabled = True Then
remaining += 1
End If
Next
LBL_Remaining.Text = CStr(remaining)
End Sub
You have to set the values of your ddlControls array while the page is loading once the DropDownList controls are already created :
Dim arr() As String = {"One", "Two", "Three", "Four", "Five"}
Dim ddlControls() As DropDownList
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
If Not IsPostBack Then
ddlControls = {DDL1, DDL2, DDL3, DDL4, DDL5} ' <<======= HERE
DDL1.DataSource = arr
DDL1.DataBind()
For Each ddl As DropDownList In ddlControls
ddl.DataSource = arr
ddl.DataBind()
Next
End If
Dim remaining As Integer
For Each ddl As DropDownList In ddlControls
If ddl.Enabled = True Then
remaining += 1
End If
Next
Me.Title = CStr(remaining)
End Sub
I need help figuring out why some controls that are inside a formview and are filled at runtime lose their contents after postback.
I have a dropdownlist (ddl_1) that I populate based on entries from another dropdownlist (ddl_2) in the same formview. All seem to work fine util a postback event occurs after which, the newly populated dropdownlist (ddl_1) is empty.
The EnableViewState for both these ddls is set to true. ddl_2 is databound but ddl_1 is not. In Page_Load in IsPostBack clause, ddl_2 is databound and then I call the function that populates ddl_1.
If I move ddl_1 outside of the formview, it retains its entries after postback just fine.
Another similar issue is with a TextBox inside the formview. When in insert mode, the contents of the TextBox disappear after postback. This does not happen in insert mode though.
What is specific to formview that causes this?
Thanks much.
Here is the Page_load code.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
If NavHelper.User.UserName = "" Then
Dim UserIP As String
Dim UserLogin As String
Dim UserEmail As String
UserIP = HttpContext.Current.Request.UserHostAddress
UserLogin = HttpContext.Current.Session("Username")
UserEmail = HttpContext.Current.Session("Email")
GetUserInfo()
CurrentRFQ = Nothing
If NavHelper.RFQ.ID = -1 Then
formview_RFQ.ChangeMode(FormViewMode.Insert)
tabpanelCustomerParts.Visible = False
tabpanelDocuments.Visible = False
tabpanelReviews.Visible = False
tabpanelRFQReviewHistory.Visible = False
listview_CustomerParts.Dispose()
Else
formview_RFQ.ChangeMode(FormViewMode.Edit)
listview_ReviewContracts_Initial.EditIndex = 0
SessionHelper.CurrentObject = TAA.Library.RFQ.GetObject(NavHelper.RFQ.ID)
mRFQ = DirectCast(SessionHelper.CurrentObject, TAA.Library.RFQ)
Dim UserdeptTotal As Long
UserdeptTotal = HttpContext.Current.Session("DepartmentTotal")
If formview_RFQ.FindControl("ddlCompanyBuyerNVList") IsNot Nothing Then
Dim ddl As DropDownList = DirectCast(formview_RFQ.FindControl("ddlCompanyBuyerNVList"), DropDownList)
FillCompanyNameDropDownList(ddl)
End If
tabpanelCustomerParts.Visible = True
tabpanelDocuments.Visible = True
tabpanelReviews.Visible = True
tabpanelRFQReviewHistory.Visible = True
If NavHelper.RFQ.Copy = True Then
SetModifyCopy()
End If
End If
Else 'IsPostBack
datasource_BuyerNVList.Dispose()
datasource_BuyerNVList.DataBind()
Dim ddl As DropDownList
If (formview_RFQ.CurrentMode = FormViewMode.Insert) Then
ddl = DirectCast(formview_RFQ.FindControl("ddlCompanyBuyerNVListInsert"), DropDownList)
ElseIf formview_RFQ.FindControl("ddlCompanyBuyerNVList") IsNot Nothing Then
ddl = DirectCast(formview_RFQ.FindControl("ddlCompanyBuyerNVList"), DropDownList)
End If
FillCompanyNameDropDownList(ddl)
End If
End If
End Sub
While binding the dropdown use the IsPostback option.
if (!IsPostback)
{
BindDropdown1();
BindDropdown2();
}
This will retain your state. If you are not using ispostback every time the dropdown will be binded when ever you refresh the page. So use ispostback for binding dropdown for the first time.
I am trying to perfrom a postback with a Dropdownlist in a Gridview in Edit Mode. I am having problems getting to the value of the drop down. I can not do this in the RowDatabound event.
Postback is not over writing the row, I am stepping into the DropDownList7_SelectedIndexChanged event where I want to perform some operations, so it hasn't even gotten there. I do have the If Postback in the page load event.
Protected Sub DropDownList7_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
Dim row As GridViewRow = DirectCast(GridView1.Rows.Item(0), GridViewRow)
Dim newNumDDL As DropDownList = row.Cells(0).FindControl("DropDownList7")
Dim newVal As Integer = newNumDDL.SelectedValue
Dim newKey As String = newNumDDL.SelectedItem.ToString
Dim newindex As Integer = newNumDDL.SelectedIndex
Issue I believe is with the findcontrol I can not find the DDL, keeps coming back nothing.
Thanks for any help.
Can you not use:
Dim newNumDDL As DropDownList = DirectCast(sender, DropDownList)
I have two DropDownLists per item on a Repeater.
I am binding both lists to two different lists on the repeater DataBound.
Both lists have an OnSelectedIndexChanged event handler which does some calculations based on the selections in both DropDownLists. Both lists also have AutoPostBack="True".
I need the calculation to be updated immediately. So I added another data binding for the repeater - on the lists' event handler.
This is the problem however - the repeater "resets" the selections to -1 and eventually the first items in both DropDownLists are displayed.
How can I make sure the selections remain after the data binding?
Here is the repeater structure:
<asp:Repeater runat="server" ID="rptCart">
<ItemTemplate>
<tr>
<td class="size"><div><asp:DropDownList runat="server" ID="_selectSize" AutoPostBack="true" OnSelectedIndexChanged="selectChange" EnableViewState="true" TabIndex="<%#Container.ItemIndex%>"></asp:DropDownList></div></td>
<td class="material"><div><asp:DropDownList runat="server" ID="_selectMaterial" AutoPostBack="true" OnSelectedIndexChanged="selectChange" EnableViewState="true" TabIndex="<%#Container.ItemIndex%>"></asp:DropDownList></div></td>
</tr>
</ItemTemplate>
</asp:Repeater>
And 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 sizeSelect As DropDownList = CType(e.Item.FindControl("_selectSize"), DropDownList)
Dim materialSelect As DropDownList = CType(e.Item.FindControl("_selectMaterial"), DropDownList)
sizeSelect.DataSource = sizeList
sizeSelect.DataBind()
materialSelect.DataSource = materialList
materialSelect.DataBind()
End If
End Sub
And finally 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
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
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.Framed
End Select
Cart.SaveOrder()
rptCart.DataSource = Cart.Order.Items
rptCart.DataBind()
End Sub
Thank you very much in advance!
You could store the old selection:
Dim sizeSelect As DropDownList = CType(e.Item.FindControl("_selectSize"), DropDownList)
Dim materialSelect As DropDownList = CType(e.Item.FindControl("_selectMaterial"), DropDownList)
Dim sizeSelectedIndex = sizeSelect.SelectedIndex
Dim materialSelectedIndex = materialSelect.SelectedIndex
' do the databinding ... '
sizeSelect.SelectedIndex = If(sizeSelectedIndex < sizeSelect.Items.Count -1, sizeSelectedIndex, -1)
materialSelect.SelectedIndex = If(materialSelectedIndex < materialSelect.Items.Count -1, materialSelectedIndex, -1)
I'm adding in asp.net (vb) an attribute to an image-button:
imgButton.Attributes.Add("myAttr", "true")
This is working fine.
Now i want to read the attribute, but it does not work:
If imgButton.Attributes("myAttr") = "true" Then
..doSomething..
How do I get this thing working?
Edit
I have an asp.net repeater.
In this repeater i have in each itemtemplate two image buttons.
If I'm clicking on an imagebutton, the other imagebutton in this row changes it's URL.
I want that this URL is saved, after clicking on another row's imagebutton.
So I'm adding in the repeater event
ItemCommand
Dim imgButton As ImageButton
If e.CommandName = "imgBtn1" Then
imgButton = CType(e.Item.FindControl("imgBtn1"), ImageButton)
imgButton.ImageUrl = "myURL"
imgButton.Attributes.Add("myAttr1", "true")
ElseIf e.CommandName = "imgBtn2" Then
imgButton = CType(e.Item.FindControl("imgBtn2"), ImageButton)
imgButton.ImageUrl = "myURL"
imgButton.Attributes.Add("myAttr2", "true")
End If
In the Page Load event I'm adding:
If Page.IsPostBack Then
Dim countRepeaterItems As Integer = myRepeater.Items.Count
Dim imgButton As ImageButton
For i As Integer = 0 To countRepeaterItems - 1
imgButton = CType(myRepeater.Items(i).FindControl("imgBtn1"), ImageButton)
If imgButton.Attributes.Item("myAttr1") = "true" Then
imgButton.ImageUrl = "myURL"
End If
imgButton = CType(myRepeater.Items(i).FindControl("imgBtn2"), ImageButton)
If imgButton.Attributes.Item("myAttr2") = "true" Then
imgButton.ImageUrl = "myURL"
End If
Next
End If
While debugging, it still skips everything, because all Attributes are empty (but actually they are not)!
Looks like for VB it should be:
If imgButton.Attributes.Item("myAttr") = "true" Then
EDIT: original answer was for C#:
Should be square brackets on the reads:
If imgButton.Attributes["myAttr"] = "true" Then
http://msdn.microsoft.com/en-us/library/kkeesb2c.aspx#Y0
I guess! May be you have (turn off the viewstate) set EnableViewState=False to the imgButton.
Take a look at this sample:
Markup:
<form id="form1" runat="server">
<asp:Button ID="Button1" runat="server" Text="Button" />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</form>
Code:
Protected Sub Button1_Click(sender As Object, e As System.EventArgs) Handles Button1.Click
If Label1.Attributes("myAttr") = "true" Then
Label1.Attributes.Add("myAttr", "false")
Label1.Text = "false is set"
Else
Label1.Attributes.Add("myAttr", "true")
Label1.Text = "true is set"
End If
End Sub
Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
Label1.Attributes.Add("myAttr", "true")
End If
End Sub
EDIT:
May be typo in ItemCommand event code.
imgButton.ImageUrl = "myURL"
imgButton.Attributes.Add("myAttr1", "true") '<----- Correction
Addressing the issue of not finding the attributes set in your page load.
I am not entirely clear on what you are trying to accomplish, but it seems likely that you are running into a problem with the order that events execute. On a post back, the page load event executes, then the event handler for the control causing the post back. If your image button causes the post back, then the attribute is not being set until after the page load event has already completed. However, assuming you are using viewstate, your attribute should be persisted and detected on the following post back.
If this is what is happening to you, then one possible way around it would be to move the code from your page load event to the page pre render event. Pre render occurs after the control's post back events have been handled, and it is one of the last points where you can hook in and make changes to your content before it is committed to viewstate.