ASP.NET AJAX Toolkit - CalendarExtender is reset on Postback - asp.net

I have an ASP.NET page that has two input elements:
A TextBox that is ReadOnly. This TextBox is the TargetControl of a CalendarExtender
A DropDownList with AutoPostBack=true
Here is the code:
<table border="0" cellpadding="0" cellspacing="0">
<tr><td colspan="2">Date:</td></tr>
<tr><td colspan="2">
<asp:TextBox ID="dateTextBox" runat="server" ReadOnly="true" />
<ajax:CalendarExtender ID="datePicker" runat="server" Format="MM/dd/yyyy" OnLoad="datePicker_Load" TargetControlID="dateTextBox" />
</td></tr>
<tr><td colspan="2">Select an Option:</td></tr>
<tr>
<td>Name: </td>
<td><asp:DropDownList ID="optionsDropDownList" runat="server" AutoPostBack="true"
OnLoad="optionsDropDownList_Load"
OnSelectedIndexChanged="optionsDropDownList_SelectedIndexChanged"
DataTextField="Name" DataValueField="ID" />
</td></tr>
<tr><td><asp:Button ID="saveButton" runat="server" Text="Save" OnClick="saveButton_Click" /></td></tr>
</table>
When the DropDownList posts back, the date selected by the user with the datePicker is reset to the current date. In addition, if I look at the Text property of dateTextBox, it is equal to string.Empty.
How do I preserve the date that the user selected on a PostBack?

Certainly you must do as others have already suggested: set readonly field dynamically rather than in markup, and make sure you are not accidentally resetting the value in Page_Load() during postbacks...
...but you must also do the following inside Page_Load(), because the CalendarExtender object has an internal copy of the date that must be forcibly changed:
if (IsPostBack) // do this ONLY during postbacks
{
if (Request[txtDate.UniqueID] != null)
{
if (Request[txtDate.UniqueID].Length > 0)
{
txtDate.Text = Request[txtDate.UniqueID];
txtDateExtender.SelectedDate = DateTime.Parse(Request[txtDate.UniqueID]);
}
}
}

The fact that the text box is read only appears to be causing this problem. I duplicated your problem using no code in any of the bound events, and the date still disappeared. However, when I changed the text box to ReadOnly=False, it worked fine. Do you need to have the textbox be read only, or can you disable it or validate the date being entered?
EDIT: OK, I have an answer for you. According to this forum question, read only controls are not posted back to the server. So, when you do a postback you will lose the value in a read only control. You will need to not make the control read only.

protected void Page_Load(object sender, EventArgs e)
{
txt_sdate.Text = Request[txt_sdate.UniqueID];
}

If you want the textbox contents remembered after the postback and still keep it as readonly control, then you have to remove the readonly attribute from the markup, and add this in the codebehind pageload:
protected void Page_Load(object sender, EventArgs e){
TextBox1.Attributes.Add("readonly", "readonly");
// ...
}

The solution to the issue is making use of Request.Form collections. As this collection has values of all fields that are posted back to the server and also it has the values that are set using client side scripts like JavaScript.
Thus we need to do a small change in the way we are fetching the value server side.
C#
protected void Submit(object sender, EventArgs e)
{
string date = Request.Form[txtDate.UniqueID];
}

I suspect your datePicker_Load is setting something and not checking if it's in a postback. That would make it happen every time and look like it was 'resetting'.

In stead of setting ReadOnly="False", set Enabled="False". This should fix your issue.

#taeda's answer worked for me. FYI, if someone uses enabled = "false" instead of readonly = "true" wont be able to use that answer, because Request[TxtDate.UniqueId] will throw a null exception.

It is not a problem of Preserving,after setting readonly = true the value of the particular textbox doesn't be returned back to server
so
Use contentEditable="false" and made readonly = false
that would prevent value is being entered other than Calendar Extender selection also returns the value of the Text box back to the server

Related

runat server field not filled when clicking on button?

I'm using an aspx file as my main page with the following code snippet:
<input type="text" runat="server" id="Password" />
<asp:Button runat="server" id="SavePassword"
Text="Save" OnClick="SavePassword_Click"/>
Then in the code behind I use:
protected void SavePassword_Click(object sender, EventArgs e)
{
string a = Password.Value.ToString();
}
Setting Password.Value in the Page_Load works as expected, but setting a to the value results in an empty string in a regardless what I type in on the page befoere I click the save button.
Am I overlooking here something?
You should add label field with name labelShow in aspx page like this
<asp:Label ID="labelShow" runat="server"></asp:Label>
Then add the string into .cs file
protected void SavePassword_Click(object sender, EventArgs e)
{
string a = Password.Value.ToString();
labelShow.Text = a.ToString();
}
I can figure several errors :
You say something about Page_Load. You should always remember Page_Load is executed at every postback. So if you write something into the textbox at Page_Load, it will erase the value typed by user. You can change this behavior by veriyfing
if(!IsPostBack)
{
// Your code
}
around your Page_Load content.
input runat="server" is not the proper way to do TextBox in ASP.Net, in most cases you should use asp:TextBox
You don't do anything with your "a" string, your current code sample does nothing, whether the Password field is properly posted or not. You can do as suggested by Ravi in his answer to display it.
I suggest you to to learn how to use VS debugger, and to read a good course on ASP.Net Webforms to learn it.

ASP.Net AjaxControlToolkit CalendarExtender not updating Textbox in code behind

Have the following:
<asp:TextBox ID="txtStart" runat="server" Enabled="false"></asp:TextBox>
<asp:Image ID="ibDateS" runat="server" ImageUrl="../SystemImages/calendar.gif" ToolTip="Click to show calendar" AlternateText="Click to show calendar" CssClass="showpointer" />
<ajaxToolkit:CalendarExtender ID="ceStart" PopupButtonID="ibDateS" Format="dd/MM/yyyy" TargetControlID="txtStart" runat="server"></ajaxToolkit:CalendarExtender>
It all works ok on the DOM and the textbox gets updated with the new date BUT when I try to get the value in code behind i.e. txtStart.Text it still has the original value set on Page_Load.
Have I missed something?
EDIT:
TextBox set originally in Page_Load (yes contained in if(!IsPostback)):
txtStart.Text = DateTime.Now.ToString("dd/MM/yyyy");
Get it later like so:
DateTime dtStart = Convert.ToDateTime(txtStart.Text);
After a bit of research apparently its an issue with setting the textbox to readonly or enabled="false" on the page. Removing this and adding the following to page_load solved the problem:
txtStart.Attributes.Add("readonly", "readonly");
if you haven't use Page.IsPostBack property of page then plz use it and try to use you pageload code inside that. It seems that it may be the problem of Page.IsPostBack,Try for that
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// Your code for databind...
}
}
Hope you understand and works for you..
Enabled false preventing it to post the latest value.

Adding default value to ASP TextBox with TextMode = Password

I've found articles about this online, but I can't seem to get it to work.
Here is my current HTML (with all the jumbled layout stuff taken out)
<asp:Login ID="LoginUser" runat="server" EnableViewState="false"
OnAuthenticate="LoginUser_Authenticate">
<LayoutTemplate>
<asp:TextBox ID="UserName" runat="server" Text="username"
CssClass="text-box login-text-box"></asp:TextBox>
<asp:TextBox ID="Password" runat="server" CssClass="text-box
login-text-box" TextMode="Password"></asp:TextBox>
</LayoutTemplate>
</asp:Login>
Here is the server-side code I found online:
protected void Page_Load(object sender, EventArgs e)
{
txtPassword.Attributes.Add("value", "defaultpassword")
}
I keep getting the message: "txtPassword does not exist in the current context".
I get that error for anything I change the, "txtPasssword", text to.
Two things.
First, you have to reference objects by their actual name. As mikhairu pointed out, "txtPassword" is not an object name. The TextBox object is "Password".
Second, and just as important, is that context matters. Your page doesn't have a "Password" textbox on it. The User control named "LoginUser" does. So you need to do one of 2 things. One option is to inherit from the Login control and add your code for setting the password, which is probably a bit beyond you and I'd consider it a bad idea anyway. Another option is to do like the following:
LoginUser.Password.Attributes.Add("value", "defaultpassword");
However, I'm not entirely sure that will work. More than likely you'll have to do:
TextBox txtPassword = (TextBox)LoginUser.FindControl("Password");
txtPassword.Attributes.Add("value", "defaultpassword");
Since your textbox lives inside the LayoutTemplate of your Login control, you must find it first.
Example:
TextBox txtPassword = (TextBox)LoginUser.FindControl("Password");
txtPassword.Attributes.Add("value", "defaultpassword");
You have to find the control first since it's NamingContainer is the Login-control not the page:
var txtPassword = (TextBox)LoginUser.FindControl("PassWord");

why a multiline textbox (inside a user control) is not holding its value after a postback?

I have a user control that have a gridview, buttons and a multi-line textbox for comments.
When the page posts back, Gridview is behaving normaly (its controls keeps their values after postback). However, the Comment textbox is always empty, no matter what I do.
protected void Page_Load(object sender, EventArgs e)
{
//This code is in the user ciontrol.
if (!IsPostBack)
{
string test = this.txtDepartmentComments.Text;
}
}
I put a break point at that line and the value is always empty. I've tried also to set the value in the code behind like:
protected void Page_Load(object sender, EventArgs e)
{
//This code is in the user ciontrol.
if (!IsPostBack)
{
this.txtDepartmentComments.Text = "Test!";
}
}
But when the page loads, the control remain empty.
Any idea why this is hapenning?
EDIT
This the ascx code (i.e. user control)
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns = "false" >
</asp:GridView>
<asp:TextBox ID="txtComments" runat="server" Columns="45" TextMode= "MultiLine"/>
<asp:Button ID="btnComplete" runat="server" Text="Completed"/>
And thid id the aspx (i.e. the parent page)
<asp:Repeater ID="rpNewHire" runat="server">
<HeaderTemplate>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<user:MyUserControl ID = "MyUserControl1" runat = "server"
DepartmentID= '<%# Eval("DepID")%>'><user:MyUserControl />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
if(!IsPostBack) is for reading values from controls after postback, you are trying to read text box value on initial load which will always be empty, remove the '!' from your condition. Also it is hard to debug your issue with out the aspx page contents, try posting the design part as well in your question.
EDIT
Your user tag is not well formatted inside repeater, it is missing closing tag and runat attribute
<user:MyUserControl runat="server" ID = "MyUserControl1" DepartmentID= '<%# Eval("DepID")%>'></user:MyUserControl>
Controls inside repeater cannot be accessed directly, you have to loop through the rows of the repeater and find your child controls and then try reading values from them, that after you bind some data to the repeater.
Check this http://msdn.microsoft.com/en-us/magazine/cc163780.aspx
Page's IsPostBack and each user controls' IsPostBack are not same.
When a user control is posted back, that particular control's IsPostBack is true, but other user controls' IsPostBack are still false.
You can use explicitly !Page.IsPostBack inside a user control to check whether its parent page is posted back or not.
if(!Page.IsPostBack){
// do something
}
Dynamically Loaded Control can not maintain values at PostBack? It is not directly related to your question, but it might be useful for you.

UpdatePanel, Repeater, DataBinding Problem

In a user control, I've got a Repeater inside of an UpdatePanel (which id displayed inside of a ModalPopupExtender. The Repeater is databound using an array list of MyDTO objects. There are two buttons for each Item in the list. Upon binding the ImageURL and CommandArgument are set.
This code works fine the first time around but the CommandArgument is wrong thereafter. It seems like the display is updated correctly but the DTO isn't and the CommandArgument sent is the one that has just been removed.
Can anybody spot any problems with the code?
Edit : I've just added a CollapsiblePanelExtender to the code. When I now delete an item and expand the panel, the item that was previously deleted (and gone from the display) has come back. It seems that the Repeater hasn't been rebuilt correctly under the bonnet.
ASCX
<asp:UpdatePanel ID="ViewDataDetail" runat="server" ChildrenAsTriggers="true">
<Triggers>
<asp:PostBackTrigger ControlID="ViewDataCloseButton" />
<asp:AsyncPostBackTrigger ControlID="DataRepeater" />
</Triggers>
<ContentTemplate>
<table width="100%" id="DataResults">
<asp:Repeater ID="DataRepeater" runat="server" OnItemCommand="DataRepeater_ItemCommand" OnItemDataBound="DataRepeater_ItemDataBound">
<HeaderTemplate>
<tr>
<th><b>Name</b></th>
<th><b> </b></th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<b><%#((MyDTO)Container.DataItem).Name%></b>
</td>
<td>
<asp:ImageButton CausesValidation="false" ID="DeleteData" CommandName="Delete" runat="server" />
<asp:ImageButton CausesValidation="false" ID="RunData" CommandName="Run" runat="server" />
</td>
</tr>
<tr>
<td colspan="2">
<table>
<tr>
<td>Description : </td>
<td><%#((MyDTO)Container.DataItem).Description%></td>
</tr>
<tr>
<td>Search Text : </td>
<td><%#((MyDTO)Container.DataItem).Text%></td>
</tr>
</table>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
</ContentTemplate>
</asp:UpdatePanel>
Code-Behind
public DeleteData DeleteDataDelegate;
public RetrieveData PopulateDataDelegate;
public delegate ArrayList RetrieveData();
public delegate void DeleteData(String sData);
protected void Page_Load(object sender, EventArgs e)
{
//load the initial data..
if (!Page.IsPostBack)
{
if (PopulateDataDelegate != null)
{
this.DataRepeater.DataSource = this.PopulateDataDelegate();
this.DataRepeater.DataBind();
}
}
}
protected void DataRepeater_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "Delete")
{
if (DeleteDataDelegate != null)
{
DeleteDataDelegate((String)e.CommandArgument);
BindDataToRepeater();
}
}
else if (e.CommandName == "Run")
{
String sRunning = (String)e.CommandArgument;
this.ViewDataModalPopupExtender.Hide();
}
}
protected void DataRepeater_ItemDataBound(object source, RepeaterItemEventArgs e)
{
RepeaterItem item = e.Item;
if (item != null && item.DataItem != null)
{
MyDTO oQuery = (MyDTO)item.DataItem;
ImageButton oDeleteControl = (ImageButton) item.FindControl("DeleteData");
ImageButton oRunControl = (ImageButton)item.FindControl("RunData");
if (oDeleteControl != null && oRunControl !=null)
{
oRunControl.ImageUrl = "button_expand.gif";
oRunControl.CommandArgument = "MyID";
if (oQuery !=null)
{
//do something
}
oDeleteControl.ImageUrl = "btn_remove.gif";
oDeleteControl.CommandArgument = "MyID";
}
}
}
public void BindDataToRepeater()
{
this.DataRepeater.DataSource = this.PopulateDataDelegate();
this.DataRepeater.DataBind();
}
public void ShowModal(object sender, EventArgs e)
{
BindDataToRepeater();
this.ViewDataModalPopupExtender.Show();
}
Thanks for reminding me why I stopped using ASP.NET controls. This is the exact type of nightmare that has made too many projects go way over budget and schedule.
My advise to you is to think of the simplest way to implement this. You can try to bend over backwards in order to get this to work the ASP.NET way or take the shortest route.
All you're doing is generating HTML, it should never be that difficult.
The most likely cause of your problem is that the ViewState is stored in the page which doesn't get updated on a partial postback. So with every change in the update panel you'll postback the initial viewstate of the page.
Try replacing the repeater with a simple for-loop (and ignore the people who start complaining you shouldn't mix markup and code). Replace your databinding statements with <%= %>.
That eliminates the view state all together and should remove any removed row from re-appearing.
After many days of messing around with this I've not found a proper fix for the problem but do have a workable work-around.
The CollapsiblePanelExtender is set to NOT postback automatically which fixes the issue of the deleted data re-appearing when the extender is opened. The other issue, I believe, is related.
It seems that the ViewState for the Repeater is out of sync with the data. e.CommandArgument is not always correct and seems to reference the previous data. I made an attempt to fix it by storing the ArrayList of MyDTO objects in the ViewState when opening the Modal dialog and using the ID retrieved from e.Item.ItemIndex to find the correct element to delete. This didn't work correctly, the ArrayList pulled out of the ViewState was out of sync.
Storing the ArrayList in the session makes it all work which leads me to believe that I'm doing something fundamentally wrong or there is a subtle bug in the version of the toolkit that i'm using (we're still on VS2005 so are stuck with an older version of the toolkit)
Apologies if this makes no sense, contact me if you want clarification on anything.
try using
((IDataItemContainer)Container).DataItem
instead of "Container.DataItem"
It worked for me.

Resources