Exclude Control from Page.Isvalid - asp.net

I have a few controls on a page that are all in the same validation group. Depending on certain conditions, one of these controls can be set to visible=false (and the user wont be able to input anything into it). If this happens, is there a way to remove said control from the validation group? Code like this:
if(testControl.Visible==false) testControl.ValidationGroup="";
does nothing. Yet, if I remove the validationgroup from the aspx page like so:
<asp:RequiredFieldValidator ID="testControl" runat="server" validationgroup=""></asp:RequiredFieldValidator>
The page will validate. Is there a way around this?

Are you sure your code is being hit in the code-behind file? I mean, your control is really invisible when you check that condition?
if(testControl.Visible == false)
testControl.ValidationGroup = string.Empty;
Put a breakpoint in testControl.ValidationGroup=""; and see if the debugger stops there.
Where is the code above? It should be inside the PageLoad method for example.
Call Page.Validate("NameOfYourValidationGroup") after that code.
What is the problem here I think:
You're setting this testControl with Visible = False and then you post back to the server. When you do testControl.ValidationGroup = string.Empty it'll have no effect because it has already posted back to the server:
From MSDN:
TextBox..::.ValidationGroup Property
Gets or sets the group of controls for
which the TextBox control causes
validation when it posts back to the
server.
This way you should call this code testControl.ValidationGroup = string.Empty; when you hide your control setting it to Visible = false so that when the page loads again for the user the control won't be assigned to that ValidationGroup. Now, if you postback the page it should validate the way you want it.
Set testControl.CausesValidation = false too.

Does the following help?:
testControl.IsValid = true;
Use for ex. with:
Page.Validate();
// manual override of specific control
testControl.IsValid = true;
// Guard
if (! Page.IsValid) return; // Or do own custom logic
// else
// Do your stuff here...

Related

ASP.NET: How do I navigate to a page after clicking a checkbox?

I have some checkboxes and a dropdownlist when the value changes I want to refresh the page while passing the new value. I tried using autopostback; however, the value is already in the url previously so when the postback occurs the value never changes.
Example:
CurrentPage: page.aspx?tab=Home&checkbox=True
Then I uncheck the checkbox so I want it to go to the following page...
IntendedPage: page.aspx?tab=Home&checkbox=False
But instead I the autopostback gives me this page...
DestinationPage: page.aspx?tab=Home&checkbox=True
Because, I handle the building of the url through a function on my page. Perhaps I'm doing something wrong by this point. If so I'd be happy to be corrected on my current setup. What I think I need to know though is how to load a custom URL on the checkbox.checkchanged event. I hope this made sense, if not let me know I'll try and clarify it. Thanks!
You could try something like this ( I have not tested, it was just an idea).
protected void CheckBox1_CheckedChanged ( object sender, EventArgs e )
{
string url = "page.aspx?tab=Home&checkbox="+ CheckBox1.Checked.ToString();
Response.Redirect ( url );
}
And then on the page:
<asp:CheckBox ID="CheckBox1" runat="server"
oncheckedchanged="CheckBox1_CheckedChanged" />
VB.NET Conversion
Protected Sub CheckBox1_CheckedChanged(sender As Object, e As System.EventArgs) Handles CheckBox1.CheckedChanged
Dim url = "page.aspx?tab=Home&checkbox=" & CheckBox1.Checked.ToString()
Response.Redirect(url)
End Sub
This is very easy to do through javascript. First add onclick="checkCheckBox(this);" to your checkbox.
<script language = "javascript" type="text/javascript">
function checkCheckBox(checkbox) {
if (checkbox.checked) {
window.location.href = '../page.aspx?tab=Home&checkbox=True';
}
else {
window.location.href = '../page.aspx?tab=Home&checkbox=False';
}
}
</script>
This should do it pretty easily.
This behavior is caused by the viewstate. The checkbox use it to persists its property, especially the checked property.
Actually, there is no out of the box link between a control and query string.
In your case, you will have two options, depending on your needs :
in the Checked event, build the expected url, and redirect the user to this page. The drawback is that you "loose" the viewstate and thus, the controls' state.
instead of using postbacks, use client side script (jQuery is your friend) to hide/show parts of the page. If the url matters, use # in the urls because it does allow staying on the same page.

Need to hide a section of my ASP.net webpage until user clicks submit

I have a page in ASP.net written in VB.net.
It is a series of checklists that the user will click on. When they click "SUBMIT" VBScripts will run in the background and post to a database.
I need to then get results from the database in a table.
I think I will use either GridView or ListView to do this. A requirement is when the user hits submit, the table will appear on the same page and the preexisting "SUBMIT" button will disappear.
Does this make sense? What may be the best way for me to go about this?
Currently I do not have the DB implemented but that is something I am planning to have in a week. I do have a "test" DB I can utilize.
Could you simply set the visibility of the button to false and the gridview to true during postback?
e.g.
If(Not IsPostBack) Then
{
submitButton.Visible = true; // show button
gridView.Visible = false; // hide grid
}
Else
{
submitButton.Visible = false; // user submitted, so hide button
gridView.Visible = true; // show grid
}
EndIf
You could also use the Wizard control, ask the Questions in Step 1 and return the response in Step 2. That is just an alternative, but the above is really the way to go.
In your Submit button code, after your VBScript runs you can just set the visibility of the Asp.net controls to false.
Something like this.
Private Sub btnSubmit_Click(sender As Object, e As EventArgs)
...
btnSubmit.visible = false
gridview1.visible = true
End Sub
Also on the .aspx page set these control to there default state so the submit button when the user first gets to the page should by visible, and the gridview to be not visible.
Hope this helps.

ASP.NET Dropdown List in Codebehind vs in ASPX page

I am generating a dropdown list in codebehind and cannot get the selectedindexchanged event to fire automatically. It works fine when put directly into the ASPX page, but I need it to be in the codebehind.
This doesn't work:
var deptList = new DropDownList
{
ID = "deptList",
DataSource = departments,
DataTextField = "deptname",
DataValueField = "deptid",
AutoPostBack = true,
EnableViewState = true
};
deptList.SelectedIndexChanged += new EventHandler(deptList_SelectedIndexChanged);
deptList.DataSource = departments;
deptList.DataTextField = "deptname";
deptList.DataValueField = "deptid";
if (!IsPostBack)
deptList.DataBind();
deptList.Items.Insert(0, new ListItem("---Select Department---", string.Empty));
writer.Write("Select a department: ");
deptList.RenderControl(writer);
but this works:
<asp:DropDownList ID="deptList" AutoPostBack="true" runat="server" OnSelectedIndexChanged="deptList_SelectedIndexChanged"></asp:DropDownList>
The problem may be if you are not adding the control to the page early enough. Controls need to be added early in the page lifecycle to get their events tied in.
You're probably doing it in the Load event, which is too late. Try adding it during the Init event or overriding the CreateChildControls method.
Edit: As Dave Swersky mentioned, make sure you do this on EVERY page request including postbacks.
You have a mesh in your code. Try to devide creating, data binding and events calling.
Example:
<asp:DropDownList ID="deptList" AutoPostBack="true" runat="server"></asp:DropDownList>
Then in code behind (Page_Load):
deptList.SelectedIndexChanged += new EventHandler(deptList_SelectedIndexChanged);
if (!IsPostBack)
{
deptList.DataTextField = "deptname";
deptList.DataValueField = "deptid";
deptList.DataSource = departments;
deptList.DataBind();
deptList.Items.Insert(0, new ListItem("---Select Department---", string.Empty));
}
To elaborate on Mike Mooney's answer: you also need to make sure you add the control back into the control tree on every postback. The control tree is recreated on each postback, read in from the markup. If you add it once programmatically and never again, there is no control in the tree to receive the event.
It appears that you are not adding the control to the controls collection. You must add the control somewhere in the control hierarchy and ensure it gets added on every postback to ensure the control exists to receive the event. By adding the control you shouldn't need to call RenderControl directly.
The problem i had was that if the drop down list didn't have AutoPostBack = true then it would never call the function.

ASP.Net - repeating input boxes on the client side using Repeater

I have the following requirement for creating a user profile in my application:
User should be able to enter multiple phone numbers/email addresses in his profile.
The screen looks somewhat like this:
- By default, on page load a single textbox for phone and email are shown.
- User can click a "+" button to add additional numbers/addresses.
- On clicking the "+" button we need to add another textbox just below the first one. User can add as many numbers/addresses as he wants. On submit, the server should collect all numbers/emails and save it in DB.
I tried using the Repeater control to do this. On page_load I bind the repeater to a "new arraylist" object of size 1. So, this renders fine - user sees a single textbox with no value in it.
When he clicks the "+" button, I ideally want to use javascript to create more textboxes with similar mark-up as the first.
My questions are these:
Can I render the new textboxes anyway using js? I notice that the HTML rendered by the repeater control is somewhat complex (names/ids) etc. and it might not be possible to correctly create those controls on client-side.
If there is a way to do #1, will the server understand that these additional inputs are items in the repeater control? Say, I want to get all the phone numbers that the user entered by iterating over Repeater.DataItems.
Conceptually, is my approach correct or is it wrong to use the Repeater for this? Would you suggest any other approach that might handle this requirement?
Coming from a Struts/JSP background, I am still struggling to get a grip on the .NET way of doing things - so any help would be appreciated.
The repeater control may be a bit of overkill for what you're trying to accomplish. It is mainly meant as a databound control for presenting rows of data.
What you can do is to dynamically create the boxes as part of the Page_Load event (C#):
TestInput.aspx :
<form id="form1" runat="server">
<asp:HiddenField ID="hdnAddInput" runat="server" />
<asp:Button ID="btnPlus" OnClientClick="setAdd()" Text="Plus" runat="server" />
<asp:PlaceHolder ID="phInputs" runat="server" />
</form>
<script type="text/javascript">
function setAdd() {
var add = document.getElementById('<%=hdnAddInput.ClientID%>');
add.value = '1';
return true;
}
</script>
TestInput.aspx.cs:
protected void Page_Load(object sender, EventArgs e)
{
if (ViewState["inputs"] == null)
ViewState["inputs"] = 1;
if (hdnAddInput.Value == "1")
{
ViewState["inputs"] = int.Parse(ViewState["inputs"].ToString()) + 1;
hdnAddInput.Value = "";
}
for (int loop = 0; loop < int.Parse(ViewState["inputs"].ToString()); loop++)
phInputs.Controls.Add(new TextBox() { ID = "phone" + loop });
}
I ended up using a PlaceHolder to dynamically add the text boxes and a HiddenField to flag when another TextBox needed to be added. Since the IDs were matching, it maintains the ViewState of the controls during each postback.
Welcome to the hairball that is dynamically-added controls in ASP.NET. It's not pretty but it can be done.
You cannot add new fields dynamically using javascript because the new field would have no representation in the server-side controls collection of the page.
Given that the requirements are that there is no limit to the number of addresses a user can add to the page, your only option is to do "traditional" dynamic ASP.NET controls. This means that you must handle the adding of the control server-side by new-ing a new object to represent the control:
private ArrayList _dynamicControls = new ArrayList();
public void Page_Init()
{
foreach (string c in _dynamicControls)
{
TextBox txtDynamicBox = new TextBox();
txtDynamicBox.ID = c;
Controls.Add(txtDynamicBox);
}
}
public void AddNewTextBox()
{
TextBox txtNewBox = new TextBox();
txtNewBox.ID = [uniqueID] // Give the textbox a unique name
Controls.Add(txtNewBox);
_dynamicControls.Add([uniqueID]);
}
You can see here that the object that backs each dynamically-added field has to be added back to the Controls collection of the Page on each postback. If you don't do this, data POSTed back from the field has nowhere to go.
If you want to user the repeater, I think the easiest way is to put the repeater in a ASP.Net AJAX update panel, add the extra textbox on the sever side.
There are definitely other way to implement this without using repeater, and it maybe much easier to add the textbox using js.
No, but you can create input elements similar to what TextBox controls would render.
No. ASP.NET protects itself from phony data posted to the server. You can't make the server code think that it created a TextBox earlier by just adding data that it would return.
The approach is wrong. You are trying to go a middle way that doesn't work. You have to go all the way in either direction. Either you make a postback and add the TextBox on the server side, or you do it completely on the client side and use the Request.Form collection to receive the data on the server side.

Manuell Postback in ASP.Net

how I can do a manuell postback in the code?
I don't want a Redirect, because e.g. the user has entered values in fields in the site and decide than to login. I only want a simple Postback.
If you have link/image buttons on you page you can do:
__doPostBack('link/image button name',''); // in javascript
or if not:
var f = document.forms[0]; //if you only have one forms(this standard on asp.net)
f.__EVENTTARGET = 'some control name';
f.submit();
What's your point? Do you want to generate a postback script?
Page.ClientScript.GetPostBackEventReference(this, "Arguments", false);
Afterward, for handling the postback you must implement the System.Web.UI.IPostbackEventHandler.
But if you want a cross postback, check it out:
http://www.c-sharpcorner.com/UploadFile/DipalChoksi/xpgpostbk_asp2_dc08102006235543PM/xpgpostbk_asp2_dc.aspx

Resources