How to clear all form fields from code-behind? - asp.net

HTML has an input button type to reset all fields in a form to their initial state in one step: <input type="reset" ... />.
Is there a similar simple way to reset all form fields of an aspx page from code-behind? Or is it necessary to reset all controls one by one with TextBox1.Text=string.Empty, TextBox2.Text=string.Empty, etc. ?
Thanks in advance!
Update:
Context is a simple Contact/"Send us a message" page with 8 asp:TextBoxes on the page (where the user enters the name, address, phone, email, message, etc.). Then he clicks on submit, the Onclick message handler in code-behind sends an email to some administrator, and all the form fields the user filled in should be emptied and he gets a notification in a label ("Message sent blabla..."). I want to have the form fields cleared to avoid that the user clicks again on submit and the same message is sent a second time.

You need only write a fork for each type of control unless one of the control has something special that needs to be done to reset it.
foreach( var control in this.Controls )
{
var textbox = control as TextBox;
if (textbox != null)
textbox.Text = string.Empty;
var dropDownList = control as DropDownList;
if (dropDownList != null)
dropDownList.SelectedIndex = 0;
...
}
ADDITION You asked how to clear controls even ones that are buried. To do that, you should create a recursive routine like so:
private void ClearControl( Control control )
{
var textbox = control as TextBox;
if (textbox != null)
textbox.Text = string.Empty;
var dropDownList = control as DropDownList;
if (dropDownList != null)
dropDownList.SelectedIndex = 0;
...
foreach( Control childControl in control.Controls )
{
ClearControl( childControl );
}
}
So, you would call this by passing the page:
ClearControls( this );

Refer this link for more information
http://www.freshcodehub.com/Article/3/clear-all-fields-like-textbox-dropdownlist-checkbox-radiobutton-label-after-form-submission-in-aspnet-c
public void ClearControls(Control parent)
{
foreach (Control c in parent.Controls)
{
if ((c.GetType() == typeof(TextBox))) //Clear TextBox
{
((TextBox)(c)).Text = "";
}
if ((c.GetType() == typeof(DropDownList))) //Clear DropDownList
{
((DropDownList)(c)).ClearSelection();
}
if ((c.GetType() == typeof(CheckBox))) //Clear CheckBox
{
((CheckBox)(c)).Checked = false;
}
if ((c.GetType() == typeof(CheckBoxList))) //Clear CheckBoxList
{
((CheckBoxList)(c)).ClearSelection();
}
if ((c.GetType() == typeof(RadioButton))) //Clear RadioButton
{
((RadioButton)(c)).Checked = false;
}
if ((c.GetType() == typeof(RadioButtonList))) //Clear RadioButtonList
{
((RadioButtonList)(c)).ClearSelection();
}
if ((c.GetType() == typeof(HiddenField))) //Clear HiddenField
{
((HiddenField)(c)).Value = "";
}
if ((c.GetType() == typeof(Label))) //Clear Label
{
((Label)(c)).Text = "";
}
if (c.HasControls())
{
ClearControls(c);
}
}
}

using the manual approach of String.Empty for each and every Textbox or any other field will be cumbersome, also by using Response.Redirect(); it will be difficult to show any confirmation message or same. So, on reading so many blogs i have found a reliable approach so far:
Public void reset(Control control)
{
foreach (Control x in control.Controls)
{
if (x is TextBox)
{
(x as TextBox).Text = String.Empty;
}
else if (x is DropDownList)
{
(x as DropDownList).SelectedIndex = 0;
}
.
.
reset(x);
}
}
use this code as reset(this); in your page wherever you want to reset or clear the values. At end of the if conditions do not forget to use the function recursively using the same
`Control` object x.

Using form.Controls.Clear() is not such a good approach because it will clear the entire form and you will even lose all the buttons on the form.
Instead if you just want to clear all the form fields like text fields and radio buttons I would recommend you try the following:
If you have a Reset button “Button1” then on click call a function reset();
In the reset function:
protected void resetButton_Click(object sender, EventArgs e)
{
TextBox1.Text=""; //set equal to empty string to all fields
}
Or redirect to same page by terminating the previous page
protected void resetButton_Click(object sender, EventArgs e)
{
Response.Redirect("~/Test2.aspx", true);
}

For your scenario the easiest way to clear the fields, in my opinion, is to turn off the ViewState (EnableViewState=false) of the controls you want to appear blank after the submit.
Or perhaps for the whole page unless there is some state you need.

Related

GridView is scrolling back to top after In-Row Button Click

I have a GridView inside an UpdatePanel. The GridView (GV) contains In-Row Buttons. If the GV list is very long and press the Buttons on the bottom rows, the page scrolls to the top and I cannot find which button I had clicked.
I have tried, MaintainScrollPositionOnPostback="true", but since I am using an UpdatePanel, this does not seem to be working.
I would like the screen to remain on the Row where I have clicked the Button.
set UpdatePanel UpdateMode="Always"
add this function:
public static string GetPostBackControlId(Page page)
{
Control control = null;
// first we will check the "__EVENTTARGET" because if post back made by the controls
// which used "_doPostBack" function also available in Request.Form collection.
string controlName = page.Request.Params["__EVENTTARGET"];
if (!String.IsNullOrEmpty(controlName))
{
control = page.FindControl(controlName);
}
else
{
// if __EVENTTARGET is null, the control is a button type and we need to
// iterate over the form collection to find it
// ReSharper disable TooWideLocalVariableScope
string controlId;
Control foundControl;
// ReSharper restore TooWideLocalVariableScope
foreach (string ctl in page.Request.Form)
{
// handle ImageButton they having an additional "quasi-property"
// in their Id which identifies mouse x and y coordinates
if (ctl.EndsWith(".x") || ctl.EndsWith(".y"))
{
controlId = ctl.Substring(0, ctl.Length - 2);
foundControl = page.FindControl(controlId);
}
else
{
foundControl = page.FindControl(ctl);
}
if (!(foundControl is Button || foundControl is ImageButton)) continue;
control = foundControl;
break;
}
}
return control == null ? String.Empty : control.ID;
}
use this in page_loadto get postback controlId:
if (IsPostBack)
{
string controlName = GetPostBackControlId(this);
}

Returning Arraylist from recursive function for ASP.Net

Please refer the attached screenshot. I have an array of the checkbox and a button for the post back in ASP.Net page. I have written a function as follows to determine what all check boxes have been checked on the button click event: The following code is a part of the business component which is called from ASP.Net. Please let me know how can I return actionArray back to calling functon in ASP.Net page.
public void checkBoxValidation(Control parent, string strKey)
{
XmlDocument getCyleXML = new XmlDocument();
string strChkID="", strActionXPath = "",strAction="";
ArrayList actionArray = new ArrayList();
// Loop through all the controls on the page
foreach (Control c in parent.Controls)
{
// Check and see if it's a checkbox.
if ((c.GetType() == typeof(CheckBox)))
{
// Since its a checkbox, see if this is checked.
if (((CheckBox)(c)).Checked == true)
{
// Find the ID of the checkbox
strChkID = ((CheckBox)(c)).ID.ToString();
getCyleXML = CycleXML(strKey);
strActionXPath = "/Actions/Action[checkbox='" + strChkID + "']/*[self::Name]";
strAction = getCyleXML.SelectSingleNode(strActionXPath).ToString();
actionArray.Add(strAction);
}
}
// Now we need to call itself (recursion) because all items (Panel, GroupBox, etc) is a container so we need to check
// all containers for any checkboxes.
if (c.HasControls())
{
checkBoxValidation(c, strKey);
}
}
}
The code should be like this :
public ArrayList checkBoxValidation(Control parent, string strKey, ArrayList actionArray)
{
XmlDocument getCyleXML = new XmlDocument();
string strChkID="", strActionXPath = "",strAction="";
if(actionArray == null) { actionArray = new ArrayList(); }
// Loop through all the controls on the page
foreach (Control c in parent.Controls)
{
// Check and see if it's a checkbox.
if ((c.GetType() == typeof(CheckBox)))
{
// Since its a checkbox, see if this is checked.
if (((CheckBox)(c)).Checked == true)
{
// Find the ID of the checkbox
strChkID = ((CheckBox)(c)).ID.ToString();
getCyleXML = CycleXML(strKey);
strActionXPath = "/Actions/Action[checkbox='" + strChkID + "']/*self::Name]";
strAction = getCyleXML.SelectSingleNode(strActionXPath).ToString();
actionArray.Add(strAction);
}
}
// Now we need to call itself (recursion) because all items (Panel, GroupBox, etc) is a container so we need to check
// all containers for any checkboxes.
if (c.HasControls())
{
checkBoxValidation(c, strKey, actionArray);
}
}
return actionArray;
}

Get reference of image button click event in gridview in http module

How do we pass the Click event of ImageButton inside a GridView to httpmodule
for linkbutton's i am doing this way:
if (request.Form.GetValues("__EVENTTARGET") != null)
{
//If it's a link button execute we can directley check for the params
if (request.Params.Get("__EVENTTARGET").Contains("xyz"))
{
//some Code
}
This is not working for ImageButton.
If you're trying to attach an event to a button within a gridview might I suggest in your base page on the prerender event parse through all gridviews on the page (use a recursive findcontrol algorithm) and look for any imagebuttons, if you find one you should then be able to attach an event to it.
EDIT:
I use something similar in the following:
public abstract class AmendmentPopUpWindow : BaseMasterPlanPage
{
// override this method if the correct save controls arent being hidden in the popups
public virtual IEnumerable<WebControl> SaveControls
{
get { return Controls.All().OfType<WebControl>().Where(c => c.ID.ToLower().Contains("save")); }
}
protected override void OnPreRender(EventArgs e)
{
if (WebConfiguration.Global_EnableAmendments && SystemVersion.HasValue)
{
foreach (var control in Controls.All())
{
if (control is RadioButton || control is TextBox || control is DropDownList || control is RadComboBox || control is CheckBox || control is CheckBoxList ||
control is RadEditor || control is RadTextBox || control is RadNumericTextBox)
{
var webControl = control as WebControl;
webControl.Enabled = false;
webControl.ForeColor = Color.Gray;
}
}
foreach (var saveControl in SaveControls)
saveControl.Visible = false;
}
base.OnPreRender(e);
}
EDIT: The .All() is an extension method defined as follows (stolen from here)
public static IEnumerable<Control> All(this ControlCollection controls)
{
foreach (Control control in controls)
{
foreach (Control grandChild in control.Controls.All())
yield return grandChild;
yield return control;
}
}
ImageButtons have an additional quasi-property in their names which identifies the mouse-coordinates (X and Y).
So to find the ImageButton's name your should iterate through posted parameters and found those which end with .x or .y:
foreach (string item in request.Form)
{
if (item.EndsWith(".x") || item.EndsWith(".y"))
{
var controlName = item.Substring(0, item.Length - 2);
// some code here
}
}
You could also cound this answer useful. It contains a more generic method to determine which control caused a postback.

ASP.Net Custom Control Render error

I am trying to create a custom control and the render method is shown below.
I get an "Object reference not set to an instance of an object" error on the bulletList.RenderControl(Writer); line.
Any ideas?
protected override void Render(HtmlTextWriter Writer)
{
if (TermSetList != null && TermSetList.Count > 0)
{
BulletedList bulletList = new BulletedList();
bulletList.Click += new BulletedListEventHandler(BulletListItem_Click);
bulletList.DisplayMode = BulletedListDisplayMode.LinkButton;
bulletList.CssClass = "tabs";
foreach (KeyValuePair<String, String> item in TermSetList)
{
ListItem listItem = new ListItem();
listItem.Text = item.Key;
listItem.Value = item.Value;
bulletList.Items.Add(listItem);
}
if (!this.Page.IsPostBack)
{
bulletList.Items[0].Selected = true;
}
bulletList.RenderControl(Writer);
base.Render(Writer);
}
}
You generally do not want to add controls during render. How your currently doing this will ensure that your click handler never gets called.
My guess as to why you are getting the error is that the control has not been added to the controls collection.
My suggestion is to move the logic to an earlier event, perhaps onload, you would not need to override the Render method then.

ASP:TextBox Value disappears in postback only when password

I have an asp.net textbox like this:
<asp:TextBox ID="PINPad" runat="server" Columns="6" MaxLength="4"
CssClass="PINTextClass"></asp:TextBox>
It is, as you might have guessed, the text box from an on screen PIN pad. Javascript fills in the values. The page is posted back every five seconds (using an update panel if that matters) to update various other unrelated items on the screen. This works just fine.
However, when I convert it to a password text box, like this:
<asp:TextBox ID="PINPad" runat="server" Columns="6" MaxLength="4"
CssClass="PINTextClass" TextMode="Password"></asp:TextBox>
Then whenever the page posts back, the text box is cleared out on the screen and the textbox is empty (though during the timer event, the value does make it back to the server.)
Any suggestions how to fix this, so that it retains its value during postback?
As a security feature, ASP.NET tries to disallow you from sending the password value back to the client. If you're okay with the security issues (i.e. it's either not really secure information or you're sure that the connection is secure), you can manually set the "value" attribute of the control, rather than using its Text property. It might look something like this:
this.PINPad.Attributes.Add("value", this.PINPad.Text);
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
if (!(String.IsNullOrEmpty(txtPwd.Text.Trim())))
{
txtPwd.Attributes["value"]= txtPwd.Text;
}
if (!(String.IsNullOrEmpty(txtConfirmPwd.Text.Trim())))
{
txtConfirmPwd.Attributes["value"] = txtConfirmPwd.Text;
}
}
}
here is another way to do it:-
using System;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebControlLibrary
{
public class PWDTextBox : TextBox
{
public PWDTextBox()
{
this.TextMode = TextBoxMode.Password;
}
public string Password
{
get
{
string val = (string)ViewState["pwd"];
if (string.IsNullOrEmpty(val))
{
return "";
}
else
{
return val;
}
}
set
{
ViewState["pwd"] = value;
}
}
public override string Text
{
get
{
return Password;
}
set
{
Password = value;
}
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
this.Text = Password;
}
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
writer.AddAttribute(HtmlTextWriterAttribute.Value, this.Password);
}
}
}
The problem of losing the password in the postback can be avoid making use of Asynchronous JavaScript calls, lets describe a typical scenario for a Login page:
Lets say we have a Login page which allows the user to change the language of its labels when the user choose a language with a dropdownlist
a solution would be to invoke selectedIndexChanged event of the dropdownlist, make a postback which goes to the server and picks up the labels in the chosen language.
in this scenario the field password will be lost due to the security feature of ASP.NET which makes passwords fields not persisted between a postbacks.
This scenario can be solved if the postback is avoided making use of Asynchronous JavaScript Technology and XML (Ajax) calls.
Add a javascript function which will be invoked from the dropdownlist control, in this case this function is assigned to the Command property of the dropdownlist in code behind:
function ValueChanged(div)
{
var table = div.getElementsByTagName("table");
if (table && table.length > 0)
{
var t = table[0].getAttribute('type');
if (t != null && (t == "DropDown"))
{
var inputs = div.getElementsByTagName("input");
if (inputs && inputs.length == 2)
{
{
Translate(inputs[1].value);
}
}
}
}
}
The Translate function takes as parameter the selected option language in the dropdown control and performs the asynchronous call as shown bellow.
function Translate(lang)
{
var request = null;
if (window.XMLHttpRequest)
{
request = new XMLHttpRequest();
if (request.overrideMimeType)
{
request.overrideMimeType('text/xml');
}
}
else if (window.ActiveXObject)
{
request = new ActiveXObject("Msxml2.XMLHTTP");
}
if (request == null)
{
return;
}
var url = "GetLoginTranslations.aspx";
request.open('GET', url +'?lang=' + lang, true);
request.setRequestHeader("Cache-Control", "no-cache");
request.setRequestHeader("Pragma", "no-cache");
request.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
request.onreadystatechange = function () { TranslateLabels(request); };
request.send(null);
}
the function Translate shown above performs the call and get the results in the specified .aspx page (in this case "GetLoginTranslations.aspx")
when the request is completed and the request.onreadystatechange is set to the function TranslateLabels this function will be executed.
on this way the postback is not executed as before in the event onSelectedIndexChanged of the dropdownlist control.
the TranslateLabels function would look something like :
function TranslateLabels(request)
{
if (request.readyState == 4)
{
if (request.status == 200)
{
if (request.responseXML)
{
var objRoot = request.responseXML.documentElement;
if (objRoot)
{
if (objRoot.nodeName == "strings")
{
for (var i = 0; i < objRoot.childNodes.length; i++)
{
var node = objRoot.childNodes[i];
var elem;
switch (node.getAttribute("id"))
{
case "lbl_login":
elem = document.getElementById("lbl_login");
if (elem)
elem.innerHTML = node.firstChild.nodeValue;
break;
}
///....
}
}
}
}
}
}
the request.responseXML contains the XML built in the page GetLoginTranslations.aspx and the structure of this XML is defined there.
the Page_Load() event in the GetLoginTranslations.aspx should look like:
protected void Page_Load(object sender, EventArgs e)
{
if (Request["lang"] != null)
strLang = Request["lang"];
//init response
Response.Clear();
Response.Cache.SetExpires(DateTime.Now);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetValidUntilExpires(true);
Response.ContentType = "application/xml";
Response.Charset = "utf-8";
XmlTextWriter xml = new XmlTextWriter(Response.OutputStream, System.Text.Encoding.UTF8)
{
Formatting = Formatting.None
};
xml.WriteStartDocument();
xml.WriteStartElement("strings");
xml.WriteStartElement("string");
xml.WriteAttributeString("id", "lbl_login");
xml.WriteString(GetTranslation("label_login", strLang));
xml.WriteEndElement();
// ... the other labels
xml.WriteEndElement(); //</strings>
xml.Close();
}
Some other considerations:
set the the property AutoPostback of the dropdownlist to false.
Happens both for view-model properties named 'Password' and 'PIN'. You can bypass the behavior by defining those as:
string Password ;
... rather than:
string Password { get; set; }
If you do so, features such the 'LabelFor' macro displaying 'DisplayAttribute.Name' no longer works, so you'd have to define those directly in the HTML.
Or you can simply name the fields something other than 'Password' or 'PIN'.

Resources