Set focus on textbox after postback - asp.net

I have a search page with 3 TextBoxes that users can filter a search with.
I have put the focus on the TextBox that contains text. If more than one contains text just focus on last TextBox.
private void SetFocusOnTextBox(ControlCollection ctrlCollection)
{
foreach (Control ctrl in ctrlCollection)
{
if (ctrl.GetType() == typeof(TextBox))
{
if (((TextBox)ctrl).Text != string.Empty)
{
SetFocus(ctrl);
}
}
}
}
After the code runs and a user searches, the focus comes to the beginning of the TextBox, not the end where it would be presumed. How to put insert marked at the end of that TextBox?

I think the answer is here: Use JavaScript to place cursor at end of text in text input element.
Taken from the linked solution: You have to add onfocus="this.value = this.value" to the three controls in the markup file. This is not so easy in ASP.NET as it should be, but one solution is to add the attribute in the code behind file.
protected void Page_Init(object sender, EventArgs e)
{
// MoveCursorToEndOnFocus is called in Page_Init and not Page_Load to avoid
// filling the ViewState with unnecessary data.
// TODO: Call MoveCursorToEndOnFocus here.
}
private void MoveCursorToEndOnFocus(ControlCollection controlCollection)
{
foreach (TextBox textBox in controlCollection
.Where(control => control.GetType() == typeof(TextBox)))
{
textBox.Attributes.Add("onchange", "this.value = this.value");
}
}

Shouldn't it be
if (((TextBox)ctrl).Text == string.Empty)
to advance to the bottommost empty textbox? If it is if (((TextBox)ctrl).Text != string.Empty), it will set focus (eventually) to the bottommost nonempty textbox.
As for advancing your cursor to the last character, try this:
function cursorToEnd( elem )
{
elem.focus();
elem.value+='x';
elem.value=elem.value.replace(/x$/,"");
}

Related

Retrieving and updating server control values in a ListView

In the past I've used jQuery Ajax to create a shopping cart. This time around I'm using the list view server control.
If I have a qty text box in each row and I want to update the quantity on a button click is this the most elegant way to achieve this?
protected void Button1_Click(object sender, EventArgs e)
{
foreach(ListViewItem item in ListViewCart.Items)
{
foreach (Control con in item.Controls)
{
if (con.GetType() == typeof(TextBox))
{
//Do Work.
}
}
}
}
I'm guessing that I would need to store the productID in a custom attribute for each textbox and use it when updating the database. (Or write more code to find that value somewhere else in the row.)
More importantly, is there a different server control I might want to use instead? I don't want to use the gridview.
I guess you could shorten it a little bit like this
foreach (TextBox txtBox in
ListViewCart.Items.SelectMany(item => item.Controls.OfType<TextBox>()))
{
//do work like - txtBox.Text = "foo";
}

textbox.text always returning empty string instead of user's entered text

I am very surprised to see last night my code was working fine and the next day suddenly my textbox.text always have empty string..
My code is:
Name of Event* :
<br />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
Code behind:
protected void Page_Load(object sender, EventArgs e) {
}
protected void create_Click(object sender, EventArgs e) {
if (!object.Equals(Session["UserLoginId"], null)) {
int mid = 0;
int cid = 0;
bool valid = true;
if (this.TextBox1.Text == "") {
error.Text = "<p style='color:red'>Marked Fields are compulsory!!</p>";
}
else {
.... // database insert ....
}
I am always ending up with an error.text value.
Why?
Had a similar problem with text boxes getting cleared on adding a new row. It was the issue of the page reloading when the add button was clicked.
Fixed the issue by adding:
Sub Page_Load
If Not IsPostBack Then
BindGrid()
End If
End Sub
Per Microsoft's documentation http://msdn.microsoft.com/en-us/library/aa478966.aspx.
Kinda mentioned but you should make sure your checking your that Post_Back event is not clearing your textbox. It would by default.
Try something like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (this.TextBox1.Text == "")
{
error.Text = "<p style='color:red'>Marked Fields are compulsory!!</p>";
}
else
{
//.....
}
}
}
I had a similar problem. I had a textarea feeding data to a database on postback. I also designed the page to populate the textarea from the same database field. The reason it failed was because I forgot to put my reload logic inside an if(!IsPostPack) {} block. When a post back occurs the page load event gets fired again and my reload logic blanked the textarea before I could record the initial value.
If the page make a post back, then all the data , the user entered ,will be erased,as the controls are stateless, so u should keep your data entry through EnableViewState = true.
I am having this issue, but i'm using Telerik Ajax request with target in javascript. I have a RadTextBox and a RadButton. I call the same code from both of them but if i call it from the textBox and request a postback, the textbox is empty in the page load. So i call RadAjaxManager.ajaxRequestWithTarget('someUserControlClientID', 'myTextBoxText');
So in the page_load, i can grab the text, in case it's not sent to the server with the arguments sent, Request.Form("__EVENTARGUMENT") will hold my textBox value.
by the way, RadAjaxManager.ajaxRequestWithTarget is like __doPostBack('targetID', 'arguments');. Hope this helps someone. I don't have time to investigate why i lose the text with this request, so this is the workaround i did.

Set focus to textbox in ASP.NET Login control on page load

I am trying to set the focus to the user name TextBox which is inside an ASP.NET Login control.
I have tried to do this a couple of ways but none seem to be working. The page is loading but not going to the control.
Here is the code I've tried.
SetFocus(this.loginForm.FindControl("UserName"));
And
TextBox tbox = (TextBox)this.loginForm.FindControl("UserName");
if (tbox != null)
{
tbox.Focus();
} // if
I'm using Page.Form.DefaultFocus and it works:
// inside page_load, LoginUser is the Login control
Page.Form.DefaultFocus = LoginUser.FindControl("Username").ClientID;
Are you using a ScriptManager on the Page? If so, try the following:
public void SetInputFocus()
{
TextBox tbox = this.loginForm.FindControl("UserName") as TextBox;
if (tbox != null)
{
ScriptManager.GetCurrent(this.Page).SetFocus(tbox);
}
}
Update: Never used a multiview before, but try this:
protected void MultiView1_ActiveViewChanged(object sender, EventArgs e)
{
SetInputFocus();
}
protected void Page_Load(object sender, EventArgs e)
{
SetFocus(LoginCntl.FindControl("UserName"));
}
You may try to do the following:
-Register two scripts (one to create a function to focus on your texbox when page is displayed, second to register id of the textbox)
this.Page.ClientScript.RegisterStartupScript(this.GetType(), "on_load",
"<script>function window_onload() \n { \n if (typeof(idLoginTextBox) == \"undefined\" || idLoginTextBox == null) \n return; \n idLoginTextBox.focus();\n } \n window.onload = window_onload; </script>");
this.Page.ClientScript.RegisterStartupScript(this.GetType(), "Focus", String.Format("<script>var idLoginTextBox=document.getElementById(\"{0}\").focus();</script>", this.loginForm.ClientID));
As the result you should get the following in your code:
<script>
function window_onload()
{
if (typeof(idLoginTextBox) == "undefined" || idLoginTextBox == null)
return;
idLoginTextBox.focus();
}
window.onload = window_onload;
</script>
<script>
var idLoginTextBox=document.getElementById("ctl00_LoginTextBox").focus();
</script>
I've been struggling with this too and I've found a solution that seems to work very well even with deeply nested controls (like AspDotNetStorefront a.k.a. ASPDNSF uses). Note the following code called from the Page_PreRender routine. I knew the name of the TextBox I wanted to give focus to and so I just called FocusNestedControl(Me, "UserName"). I just used Me here because all the routine needs is a parent of the control to get focus; it doesn't matter which parent.
Public Function FocusNestedControl(ByVal ParentControl As Control, ByVal ControlNameToFocus As String) As Control
If ParentControl.HasControls Then
For Each childCtrl As Control In ParentControl.Controls
Dim goodCtrl As Control = FocusNestedControl(childCtrl, ControlNameToFocus)
If goodCtrl IsNot Nothing Then
goodCtrl.Focus()
Return goodCtrl
End If
Next
Else
If ParentControl.ID = ControlNameToFocus Then
ParentControl.Focus()
Return ParentControl
End If
End If
Return Nothing
End Function
You can set focus directly on LoginControl and it will automatically set focus on first field in control. In your case:
this.loginForm.Focus();
More info on MSDN: How to: Set Focus on ASP.NET Web Server Controls
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
Login.FindControl("UserName").Focus();
}
My problem arrized when i moved login control to a custom control and tried to find UsernameTextBox at the OnInit() method.
OnInit of a control is executed before OnInit of Page and this is why no Form control have been created.
I moved the call to UsernameTextBox to the OnLoad function and it worked correctly.
None of the above answers worked for me, so I simply tried:
protected void Page_Load(object sender, EventArgs e) {
// This works for me
TxtMyTextBoxName.Focus();
}
... and it worked!
With an ASP TextBox defined as:
<asp:TextBox ID="TxtMyTextBoxName" type="search" runat="server"></asp:TextBox>
You must put your textbox inside this code on ASP.NET
<form id="WHATEVERYOUWANT" runat="server" method="post">
<div>
<!-- Put your code here-->
</div>
</form>

clear textbox after postback

I have a textbox and a button on the ascx page.
After entering text i click on the button where it will post to the database and clear the textbox.
After positing, if i refresh the web page it is going to the button click method and posting the old text to the database. how can i clear the textbox value from the view state.
i have set the enableviewstate of the textbox to false. But still it is not working. Please let me know. Thanks
protected void Button_Click(object sender, EventArgs e)
{
var txt=textBox1.Text;
textBox1.Text="";//Set it to empty
// do other stuff
............
............
}
protected void btnClear_Click(object sender, EventArgs e)
{
ClearControls();
}
private void ClearControls()
{
foreach (Control c in Page.Controls)
{
foreach (Control ctrl in c.Controls)
{
if (ctrl is TextBox)
{
((TextBox)ctrl).Text = string.Empty;
}
}
}
}
After you save your data with the click button you can set the textbox.text = ""
EDIT: After your comment that textbox.text = "" is not working....
When you hit the refresh it sounds like it is resubmitting your work again. Try just reloading the page by browsing to your page again.
Also be sure to check that you aren't saving your data on every postback but just on the button click event.
Do you have any code in your page load event?
Long shot here, but this worked in my case:
TextBox.Attributes.Remove("value");
This was on a textbox with the text mode sent to 'Password'.
just add this at the end of the event after page i going o be refresh
Response.Redirect("Registration.aspx");
here my WebForm name is "Registration.aspx" instead of this put your WebForm name.

How to programmatically create and use a list of checkboxes from ASP.NET?

I have a page with a table of stuff and I need to allow the user to select rows to process. I've figured out how to add a column of check boxes to the table but I can't seem to figure out how to test if they are checked when the form is submitted. If they were static elements, I'd be able to just check do this.theCheckBox but they are programaticly generated.
Also I'm not very happy with how I'm attaching my data to them (by stuffing it in there ID property).
I'm not sure if it's relevant but I'm looking at a bit of a catch-22 as I need to known which of the checkboxes that were created last time around were checked before I can re-run the code that created them.
Edit:
I've found an almost solution. By setting the AutoPostBack property and the CheckedChanged event:
checkbox.AutoPostBack = false;
checkbox.CheckedChanged += new EventHandler(checkbox_CheckedChanged);
I can get code to be called on a post back for any check box that has changed. However this has two problems:
The call back is processed after (or during, I'm not sure) Page_Load where I need to use this information
The call back is not called for check boxes that were checked when the page loaded and still are.
Edit 2:
What I ended up doing was tagging all my ID's with a know prefix and stuffing this at the top of Form_Load:
foreach (string v in this.Request.Form.AllKeys)
{
if (v.StartsWith(Prefix))
{
var data = v.Substring(Prefix.Length);
}
}
everything else seems to run to late.
I'm going to assume you're using a DataList but this should work with and Control that can be templated. I'm also going to assume you're using DataBinding.
Code Front:
<asp:DataList ID="List" OnItemDataBound="List_ItemDataBound" runat="server">
<ItemTemplate>
<asp:CheckBox ID="DeleteMe" runat="server"/>
<a href="<%# DataBinder.Eval(Container, "DataItem.Url")%>" target="_blank">
<%# DataBinder.Eval(Container, "DataItem.Title")%></a>
</ItemTemplate>
</asp:DataList>
<asp:Button ID="DeleteListItem" runat="server" OnClick="DeleteListItem_Click" ></asp:Button>
Code Behind:
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadList();
}
protected void DeleteListItem_Click(object sender, EventArgs e)
{
foreach (DataListItem li in List.Items)
{
CheckBox delMe = (CheckBox)li.FindControl("DeleteMe");
if (delMe != null && delMe.Checked)
//Do Something
}
}
LoadList();
}
protected void LoadList()
{
DataTable dt = //Something...
List.DataSource = dt;
List.DataBind();
}
protected void List_ItemDataBound(object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
string id = DataBinder.Eval(e.Item.DataItem, "ID").ToString();
CheckBox delMe = (CheckBox)e.Item.FindControl("DeleteMe");
if (delMe != null)
delMe.Attributes.Add("value", id);
}
}
}
First, make sure that each Checkbox has an ID and that it's got the 'runat="server"' in the tag.
then use the FindControl() function to find it.
For example, if you're looping through all rows in a GridView..
foreach(GridViewRow r in Gridview1.Rows)
{
object cb = r.FindControl("MyCheckBoxId");
if(r != null)
{
CheckBox chk = (CheckBox)cb;
bool IsChecked = chk.Checked;
}
}
Postback data is restored between the InitComplete event and the PreLoad event. If your checkboxes are not created until later then the checkboxes will play "catch up" with their events and the data will be loaded into the control shortly after it is created.
If this is to late for you then you will have to do something like what you are already doing. That is you will have to access the post data before it is given to the control.
If you can save the UniqueId of each CheckBox that you create then can directly access the post data without having to given them a special prefix. You could do this by creating a list of strings which you save the ids in as you generate them and then saving them in the view state. Of course that requires the view state to be enabled and takes up more space in the viewstate.
foreach (string uniqueId in UniqueIds)
{
bool data = Convert.ToBoolean(Request.Form[uniqueId]);
//...
}
Your post is a little vague. It would help to see how you're adding controls to the table. Is it an ASP:Table or a regular HTML table (presumably with a runat="server" attribute since you've successfully added items to it)?
If you intend to let the user make a bunch of selections, then hit a "Submit" button, whereupon you'll process each row based on which row is checked, then you should not be handling the CheckChanged event. Otherwise, as you've noticed, you'll be causing a postback each time and it won't process any of the other checkboxes. So when you create the CheckBox do not set the eventhandler so it doesn't cause a postback.
In your submit button's eventhandler you would loop through each table row, cell, then determine whether the cell's children control contained a checkbox.
I would suggest not using a table. From what you're describing perhaps a GridView or DataList is a better option.
EDIT: here's a simple example to demonstrate. You should be able to get this working in a new project to test out.
Markup
<form id="form1" runat="server">
<div>
<table id="tbl" runat="server"></table>
<asp:Button ID="btnSubmit" runat="server" Text="Submit"
onclick="btnSubmit_Click" />
</div>
</form>
Code-behind
protected void Page_Load(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
var row = new HtmlTableRow();
var cell = new HtmlTableCell();
cell.InnerText = "Row: " + i.ToString();
row.Cells.Add(cell);
cell = new HtmlTableCell();
CheckBox chk = new CheckBox() { ID = "chk" + i.ToString() };
cell.Controls.Add(chk);
row.Cells.Add(cell);
tbl.Rows.Add(row);
}
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
foreach (HtmlTableRow row in tbl.Rows)
{
foreach (HtmlTableCell cell in row.Cells)
{
foreach (Control c in cell.Controls)
{
if (c is CheckBox)
{
// do your processing here
CheckBox chk = c as CheckBox;
if (chk.Checked)
{
Response.Write(chk.ID + " was checked <br />");
}
}
}
}
}
}
What about using the CheckBoxList control? I have no Visual Studio open now, but as far as I remember it is a DataBound control, providing DataSource and DataBind() where you can provide a list at runtime. When the page does a postback you can traverse the list by calling something like myCheckBoxList.Items and check whether the current item is selected by calling ListItem.Selected method. This should work.
Add them in an override of the CreateChildControls method of the Page. Be sure to give them an ID! This way they get added to the control tree at the correct time.
IMHO The best way would be to use DataBound Templated Control though, i.e. something like a ListView (in .NET 3.5). then in pageload after postback traverse all items in the databound control and use item.FindControl to get at the actual checkbox.
What I ended up doing was tagging all my ID's with a know prefix and stuffing this at the top of Form_Load:
foreach (string v in this.Request.Form.AllKeys)
{
if (v.StartsWith(Prefix))
{
var data = v.Substring(Prefix.Length);
}
}
everything else seems to run to late.

Resources