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.
Related
I'm relatively new to using VB, and am trying to do the following:
Select DropDownList item upon Button click
Link DropDownList items to internal pages
I feel like this is basic stuff, but am having a hard time with it.
Is this correct?
1 .
<asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True">
<asp:ListItem Value="Answer.aspx">Answer</asp:ListItem>
2 .
<asp:Button ID="Button1" runat="server" Text="Button" onselectedindexchanged="DropDownList1_SelectedIndexChanged" />`
You will need to change your code a little bit to achieve this. First, you do not need the AutoPostback on the dropdown list unless you want it to hit the server when you select a new list item.
On the button click, you will want to remove the
OnSelectedIndexChange="DropDownList1_SelectedIndexChanged"
And replace it instead with the button's OnClick event.
OnClick = "Button1_Click"
You will need to add your vb code to redirect to the new page. I'm more of a C# guy, but this should work.
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim LinkText as string
LinkText = DropdownList1.SelectedItem.Value
Response.Redirect(LinkText)
End Sub
Are you trying to say, after clicking the button, it will go to the other page by selecting in dropdownlist what page it is? If I'm correct, here's how it is.
Private Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DropDownList1.SelectedIndexChanged
Response.Redirect(DropDownList1.SelectedValue.ToString)
End Sub
This is a difficult scenerio to explain, so I coded up a simple example.
<asp:UpdatePanel runat="server" ID="upTest" ChildrenAsTriggers="true"
UpdateMode="Conditional">
<ContentTemplate>
<asp:DropDownList ID="ddlTest" runat="server" AutoPostBack="true"></asp:DropDownList>
<br /><br />
In page: <asp:TextBox runat="server" ID="txtTest" Columns="50" Text="OnLoad</asp:TextBox>
<br />
<br />
<asp:Button runat="server" ID="btnTest" Text="Click it" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="ddlTest" />
</Triggers>
</UpdatePanel>
Code-Behind
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Page.IsPostBack Then
BindDropDown(Request.Form(ddlTest.UniqueID))
Else
BindDropDown(0)
End If
End Sub
Public Sub BindDropDown(val As Integer)
ddlTest.Items.Add(New ListItem("", 0))
ddlTest.Items.Add(New ListItem("One", 1))
ddlTest.Items.Add(New ListItem("Two", 2))
ddlTest.Items.Add(New ListItem("Three", 3))
ddlTest.Items.Add(New ListItem("Four", 4))
ddlTest.SelectedValue = val
End Sub
Private Sub ddlTest_SelectedIndexChanged(sender As Object, e As System.EventArgs) Handles ddlTest.SelectedIndexChanged
txtTest.Text = "Dropdown changed"
End Sub
Private Sub btnTest_Click(sender As Object, e As System.EventArgs) Handles btnTest.Click
txtTest.Text = "Button clicked"
End Sub
Also to note, I have EnableViewState="false" and ClientIdMode="Static" for the page.
When I click the button the partial postback occurs and the textbox has the expected value of 'Button Clicked'
When I change the dropdown the partial postback occurs, however the textbox does not have the expected value of 'Dropdown changed' because the code in ddlTest_SelectedIndexChanged is never hit (breakpoint placement on that line of code also never hits)
In the larger scope of my project this is the crux of the problem and I can't determine why this event is never hit (the core problem is when I load a dynamic user control, the data in the control is bound correctly, but then is overridden with the pre-post data after the user control is loaded - the override is occurring somewhere in the post back events). It appears to me it has something to do with the binding of the dropdown and where it happens in the page cycle, but I haven't been able to nail anything down, nor come up with google solutions.
One odd thing I did notice when looking at the post in Firebug - the EVENTTARGET value for the dropdown was the UniqueId of the dropdown, but the EVENTTARGET value is empty for the button click. My brain is thinking there is some connection here.
FYI - I have come up with a work around that seems to do the trick. I set autopostback on dropdown to false, and using jQuery I assign the change event on the dropdown to fire the button click - which causes the postback and fires btn_click event in code.
I solved the initial issue here by moving the dropdown fill to the init event and then letting .NET load the selected value from view state
However in doing this, now the selectedindex event fires on EVERY postback.
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.
I have the following button:
<asp:ImageButton ID="imgbtnEditInfo" runat="server" ImageUrl="~/images/EditInformation.png" AlternateText="EditInformation" CommandName="EditDetails" CommandArgument="<%# Container.DataItemIndex %>" OnClick="lnkEdit_Click" Enabled="true" />
I have the following method but looks like it is not hitting the method:
Protected Sub lnkEdit_Click(ByVal sender As Object, ByVal e As System.EventArgs)
End Sub
Wondering if I am missing something. I put a breakpoint on the Protected Sub lnkEdit_Click but on click of the imagebutton I do not go there.
You're working with Data Controls (GridView or DataList etc). To respond to the button/linkbutton/imagebutton events, you must have to handle the parent - data control's events.
Without seeing more of your page it is hard to say. A couple things to check:
Is the ImageButton inside a <form runat="server">?
Have you compared your page to the VB sample at ImageButton Class to see if anything might have been missed?
I must be doing something wrong. I can't seem to execute my CustomValidator's ServerValidate method.
I've got a Visual Basic ASP.NET page with a CustomValidator...
<asp:TextBox ID="TextBox1" runat="server" />
<asp:CustomValidator ID="CustomValidator1" runat="server"
ControlToValidate="TextBox1"
ErrorMessage="Friendly message goes here."
Display="Dynamic" />
<asp:Button ID="Button1" runat="server"
Text="Submit"
CausesValidation="True" />
For this test, I've got the validation set to always fail...
Sub CustomValidator1_ServerValidate(ByVal source As Object, ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs) Handles CustomValidator1.ServerValidate
args.IsValid = False
End Sub
But, when the button is clicked, the CustomValidator1_ServerValidate() method never executes!
Protected Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Page.Validate()
If Page.IsValid Then
'it executes the code here!
End If
End Sub
Not even if I explicitly validate that control...
CustomValidator1.Validate() 'does nothing?
What am I doing wrong?
Add the property:
ValidateEmptyText="True"
Are you putting the validator control submit button in the same validation group?
Firstly, You seem to be missing the OnServerValidate attribute in your markup above.
Secondly, I would check to ensure that CustomValidator1_ServerValidate has been set up as an eventhandler for the ServerValidate event for Textbox1. I have had occasions where I have changed the name of the validate method in the markup and code-behind, but the IDE has not auto updated the subscribing method name passed to the eventhandler delegate
I know it's a daft question (or might sound like it!). But have you actually entered or changed the value in the textbox? I think the validator won't trigger without the contents of the textbox changing.