I am using master page with content pages. I want to write a genral method to clear textboxes and for dropdownlist set index to 0. Please guide on this.
A Server-Side Approach
If you want to clear the TextBoxes and DropDownLists on postback, you could recurse through the page's Controls collection and for each control see if it's a TextBox or DropDownList. Here's such a function in C#:
void ClearInputs(ControlCollection ctrls)
{
foreach (Control ctrl in ctrls)
{
if (ctrl is TextBox)
((TextBox)ctrl).Text = string.Empty;
else if (ctrl is DropDownList)
((DropDownList)ctrl).ClearSelection();
ClearInputs(ctrl.Controls);
}
}
To use this you'd call ClearInputs passing in the control collection you want to search. To clear out all TextBoxes and DropDownLists on the page you'd use:
ClearInputs(Page.Controls);
A Client-Side Approach
An alternative tactic would be to use a client-side approach. Namely, use JavaScript to recurse through the DOM and clear/reset the textboxes and drop-downs on this page. The following JavaScript uses the jQuery library to simplify things:
function clearElements() {
$("input[type=text]").val('');
$("select").attr('selectedIndex', 0);
}
In a nutshell, it sets the value of all <input type="text" ... /> elements on the page to an empty string and sets the selectedIndex attribute of all <select> elements on the page to 0. I've created a script on JSFiddle.net to let you try out the script: http://jsfiddle.net/xs6G9/
For More Information
I wrote a blog entry on this topic with more information and discussion. See: Resetting Form Field Values in an ASP.NET WebForm.
Happy Programming!
<input type="reset"> is a simple solution client side.
Related
I'm having problems looping through controls that are on my user control.
I have tried the following code, but cannot get it to find the checkboxes that are on the user control. (You can see some of my previous attempts that I have commented out.)
'For Each Ctrl As Control In Page.Controls
'For Each Ctrl As Control In Me.Page.Controls
'For Each ctrl As Control In Request.Form
'''Dim frm As Control = Me.FindControl("frmDefault")
'''For Each Ctrl As Control In frm.Controls
Dim Check As CheckBox
For Each Ctrl As Control In Me.Controls
If TypeOf Ctrl Is CheckBox Then
Check = Ctrl
' Do something here...
End If
Next
There are multiple chekcboxes on the user control. The code shown above is on the code behind page for the user control.
(The user control is being used in conjunction with my CMS, Sitecore. I'm not sure if this has any effect on the problem I am experiencing or not.)
Any suggestions?
Sitecore has no effect on walking through the control-collection, this should be possible.
Are you looping through the right Control-Collection? Is Me.Controls your Page-, UserControl- or RepeaterItems-Control collection (or another collection)?
If the checkboxes are nested in another control, you need to walk to that control-collection.
Maybe you should add your .ascx code so we can see what your control-collection looks like.
Does this bring up the names of the checkboxes?
For Each Ctrl As Control In Me.Controls
If TypeOf Ctrl Is CheckBox Then
MsgBox(Ctrl.Name)
End If
Next
That should let you know if you are hitting you checkboxes. If not rexamine your page design.
I believe you should have no problem assigning ctrl to check, it should act as a pointer to ctrl. If you have more than one checkbox on the page, do an if statement against the ctrl.name to get the correct one.
I finally figured out what is going on.
I have the checkboxes inside different tables. These tables contains runat="server". This table is inside a Div tag that also contains a runat="server".
My code could never find the checkboxes because of this. I had to add a For Each that loops through the Div tag and find the appropriate table(s). I then had to loop through the tables in order to find the checkboxes.
Some of your controls have controls. Your loop will ignore those controls. I have some extension methods I use to get all controls (you can specify type CheckBox so you don't need to do the type check in your calling code)
<Extension()> _
Public Function ChildControls(ByVal parent As Control) As List(Of Control)
Return ChildControls(Of Control)(parent)
End Function
<Extension()> _
Public Function ChildControls(Of T As Control)(ByVal parent As Control) As List(Of T)
Dim result As New ArrayList()
For Each ctrl As Control In parent.Controls
If TypeOf ctrl Is T Then result.Add(ctrl)
result.AddRange(ChildControls(Of T)(ctrl))
Next
Return result.ToArray().Select(Of T)(Function(arg1) CType(arg1, T)).ToList()
End Function
Well, I solved it as follows. (c#)
foreach (Control c in Page.Controls)
{
foreach (Control childc in c.Controls)
{
if (childc.ClientID == "menupadraolateral1")
{
foreach (Control cMnuLat in childc.Controls)
{
//here you can access the controls of usercontrol
}
}
}
}
Where "menupadraolateral1" is the ID used where the usercontrol is called
I hope I have helped
I load a piece of html which contains something like:
<em> < input type="text" value="Untitled" name="ViewTitle" id="ViewTitle" runat="server"> </em>
into my control. The html is user defined, do please do not ask me to add them statically on the aspx page.
On my page, I have a placeholder and I can use
LiteralControl target = new LiteralControl ();
// html string contains user-defined controls
target.text = htmlstring
to render it property. My problem is, since its a html piece, even if i know the input box's id, i cannot access it using FindControl("ViewTitle") (it will just return null) because its rendered as a text into a Literal control and all the input controls were not added to the container's control collections. I definitely can use Request.Form["ViewTitle"] to access its value, but how can I set its value?
Jupaol's method is the prefer way of adding dynamic control to a page.
If you want to insert string, you can use ParseControl.
However, it doesn't cause compilation for some controls such as PlaceHolder.
Your process is wrong, you are rendering a control to the client with the attribute: runat="server"
This attribute only works if the control was processed by the server, you are just rendering as is
Since your goal is to add a TextBox (correct me if I'm wrong), then why don't you just add a new TextBox to the form's controls collection???
Something like this:
protected void Page_Init(object sender, EventArgs e)
{
var textbox = new TextBox { ID="myTextBoxID", Text="Some initial value" };
this.myPlaceHolder.Controls.Add(textbox);
}
And to retrieve it:
var myDynamicTextBox = this.FindControl("myTextBoxID") as TextBox;
I have created several working examples and they are online on my GitHub site, feel free to browse the code
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.
I have two pages on my site which are populated with content from a database as well as having user-entered fields (don't ask!). The pages also contain a ListView with a nested DataList. There are buttons on these pages which when clicked grab the html content of the page, write it to a HtmlTextWriter then get the text and put it into an email.
What I need to do is replace any TextBox / DropDownLists in the html source with string literal equivalents before putting into the email.
My aspx code so far looks something like this:
<div id="mailableContent" runat="server">
<asp:TextBox ID="txtMessage" runat="server"/>
<asp:Label ID="lblContentFromDb" runat="server"/>
<asp:ListView ID="lvwOffices" runat="server">
//loads of stuff here including more textboxes for the user to fill in
</asp:ListView>
</div>
and the codebehind is something like this:
StringBuilder stringBuilder = new StringBuilder();
StringWriter writer = new StringWriter(stringBuilder);
HtmlTextWriter htmlWriter = new HtmlTextWriter(writer);
mailableContent.RenderControl(htmlWriter);
MailMessage message = new MailMessage();
//do more stuff to set up the message object
message.Body = stringBuilder.ToString();
//send the message
My ideas so far are to 1. manually set any textboxes to Visible=false then populate literal controls with corresponding textbox values which is rather messy and tedious. Note I have to strip out input controls otherwise html for the email needs to be wrapped with a form elemen which I don't really want to do.
Is there a better way to do all this, I'm thinking that perhaps doing some .Net1.1 style xslt transforms with page content defined in xml files might be a better way to approach this, but am unsure if this will handle my requirement where I'm currently using a ListView with a nested DataList.
I find what you are describing to have a lot of overhead. Does your email template stay prety much the same? if so why not simply have a simple html template with html 3 code. Then simply read this file from disk and replace specific peices (ie. ##Name##) with the dynamic content. This way you have complete control over the html being sent via email and you can control what users input.
this would also limit the amout of work to make the html compatible with email clients.
Clarification: In the preceding suggestion, I propose that the UI implementation and the Email implementation be distinct, this in turn allows to to compose the email with more flexibility. Without using
mailableContent.RenderControl(htmlWriter);
this also allows you to compose the contents of the ListView to your specifications.
Couple of ideas:
Use RegEx to replace the html output of the textboxes and dropdownlists with plaintext. (Tricky, with the complication of finding the <option selected="selected"> stuff.
Do what I do:
Create an interface e.g. IPlainTextable
Make the interface enforce a boolean property called PlainTextMode (set false by default)
Extend TextBox and DropDownList with your own controls that implement IPlainTextable
In the Render section of your extended webcontrols, render out the plaintext value if PlainTextMode is true. e.g for your subclass of TextBox
protected override void Render(HtmlTextWriter writer)
{
if (PlainTextMode)
writer.WriteLine(this.Text);
else
base.Render(writer);
}
Before rendering out your page, run through all the IPlainTextable controls and set the PlainTextMode to true.
I have written a nifty little method for iterating through a nested control set:
public static List<T> FindControlsOfType<T>(Control ctlRoot)
{
List<T> controlsFound = new List<T>();
if (typeof(T).IsInstanceOfType(ctlRoot))
controlsFound.Add((T)(object)ctlRoot);
foreach (Control ctlTemp in ctlRoot.Controls)
{
controlsFound.AddRange(FindControlsOfType<T>(ctlTemp));
}
return controlsFound;
}
So you would just do something like:
foreach (IPlainTextable ctl in FindControlsOfType<IPlainTextable>(this))
{
ctl.PlainTextMode = true;
}
and then do your render to string after that...
I have the following situation:
A user will define a certain filter on a page, and on postback I will query the database using that filter and return a bunch of matching records to the user, each with a checkbox next to it, so he can choose whether to act on each of those records.
In Classic ASP / PHP I can generate a lot of controls named "chk__*" and then on postback go through all the $POST entries looking for the ones prefixed "chk".
What is the best way to do this in ASP.Net 2.0?
I can do it easily by implementing a Repeater with a Template containing the checkbox, bind the Repeater to a Dataset, and then on the second Postback, I just do:
For Each it As RepeaterItem In repContacts.Items
Dim chkTemp As CheckBox = DirectCast(it.FindControl("cbSelect"), CheckBox)
If chkTemp.Checked Then
End If
Next
However this has the slight disadvantage of giving me a HUGE Viewstate, which is really bad because the client will need to re-upload the whole viewstate to the server, and these people will probably be using my site over a crappy connection.
Any other ideas?
(I can also create the controls dynamically and iterate through Request.Form as in the old days, however, I was looking for a cleaner
Have you looked at the CheckBoxList control? You can bind it to your data set, provide text member and value member items, and it will also allow you to easily see which items are checked. There is also the ability to dynamically add more checkbox items if needed.
Do it the same way you did it in classic ASP. Use <input type="checkbox"> instead of <asp:checkbox>. You can access the raw post paramaters using Request.Form
I recommend the classic ASP solution when faced with absurd Viewstate conditions. It is sad to lose the nice features it provides, but combining some Viewstate enabled controls (asp:*) with some classic techniques (input type="...") has saved me a lot of headaches in the past.
Sometimes you just want to do something simple, and the simple solution beats "WYSIWYG" form editing.
One of the things that I have done is to record the state of a check via AJAX in the session, then on Postback (full or partial via AJAX), look in the session for the items to perform the selected action on.
The basic idea is to add an onclick handler to the checkbox that knows the id of the associated item. In the on click handler communicate this id back to the server via AJAX and record it in the session -- you'll need to communicate checkbox status as well so you can uncheck items. Have the handler for the submit control use the data about which items were selected from the session.
This way allows you to handle paged data as well, since you can set the initial value of the checkbox from the session when rendering (either full or partial) a page with checked items on it.
It might look something like this. Assuming ASP.NET AJAX with PageMethods (and ScriptManager, of course).
<script type='text/javascript'>
function record(checkbox,item)
{
var context = { ctl : checkbox };
PageMethods.Record(item,checkbox.checked,onSuccess,onFailure,context);
}
function onSuccess(result,context)
{
// do something, maybe highlight the row, maybe nothing
}
function onFailure(error,context)
{
context.ctl.checked = false;
alert(error.get_Message());
}
</script>
...
<tr><td><input type='checkbox' onclick='record(this,"item_1");'></td><td>Item 1</td></tr>
...
Codebehind
[WebMethod(EnableSessionState=true)]
public static void Record( string itemName, bool value )
{
List<string> itemList = (List<string>)Session["Items"];
if (itemList == null)
{
itemList = new List<string>();
Session["Items"] = itemList;
}
if (itemList.Contains(itemName) && !value)
{
itemList.Remove(itemName);
}
else if (!itemList.Contains(itemName) && value)
{
itemList.Add(itemName);
}
}
protected void button_OnClick( object sender, EventArgs e )
{
List<string> itemList = (List<string>)Session["Items"];
if (itemList != null)
{
foreach (string item in itemList)
{
// do something with the selected item
}
}
}
Disable the ViewState. In case it cannot be done try using Session to store the view state