I am running into a problem with Ajax and C# asp.net. I am using Microsoft Visual Studio 2010.
First let me explain my web page.
I have script manager, and directly underneath that I have a update panel.
This is the dynamic placeholder I've been fiddling with.
http://www.denisbauer.com/ASPNETControls/DynamicControlsPlaceholder.aspx
Within my update panel, I have a dynamic control & a button.
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<asp:ScriptManager ID="ScriptManager1" runat="server" >
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<DBWC:DynamicControlsPlaceholder ID="DynamicControlsPlaceholder1"
runat="server">
</DBWC:DynamicControlsPlaceholder>
<br />
<asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
</asp:Content>
Now in my code behind:
I simply add 5 text boxes to a dynamic control. Page load;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
ViewState["id"] = 0;
int id = (int)ViewState["id"];
for (int i = 0; i < 5; i++)
{
id++;
TextBox txt = new TextBox();
txt.ID = id.ToString();
DynamicControlsPlaceholder1.Controls.Add(txt);
txt.Text = i.ToString();
}
ViewState["id"] = id;
}
}
Now all my button does is add another TextBox to the dynamic control pannel.
protected void Button1_Click(object sender, EventArgs e)
{
int id = (int)ViewState["id"];
TextBox txt = new TextBox();
txt.ID = id.ToString();
DynamicControlsPlaceholder1.Controls.Add(txt);
// DynamicControlsPlaceholder1.DataBind();
txt.Text = id.ToString();
id++;
ViewState["id"] = id;
}
* Note I am using a custom dynamic control panel so their ID's are saved to the next page even though we have them creeated in a !Page.IsPostBack
The problem is that my button event handler only works once. I'm pretty sure its because the Ajax is calling a partial postback and it's not recognizing it to call my button event handler.
I'm not sure, any help is appriciated.
Firebug works wonders for debugging ajax. "There were multiple controls with the same ID '5'."
What a simple fix. Moved id++; to the top of Button1_Click event handler.
If you're ever assuming ajax is breaking your event handler just because the breakpoint is not firing in the event handler, firebug may save you too!
There was absolutely nothing wrong with the event handler, but the code within it was causing an error and ajax wasn't allowing it to break.
Related
I have 2 textbox on my page and a Button. When I click on a button, the text from the textbox is emailed. But, then when i refresh the page and no content is there, then also i get an email.
protected void Button1_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(TextBox1.Text) && !string.IsNullOrEmpty(TextBox2.Text))
{
//email logic
TextBox1.Text = "";
TextBox2.Text = "";
}
else
{
//do nothing
}
}
Here, on clicking the button, i get an email but then when i refresh the page, even though there is no data, then also it goes inside the loop and i get an email.
How do i stop this ?
Do the following in your Page_Load event and keep your TextBoxes and Button in an <asp:UpdatePanel>. Then the page will not ask to re-submit each time you refresh the page.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
TextBox1.Text = string.Empty;
TextBox2.Text = string.Empty;
}
}
UPDATE
Keep the controls within an UpdatePanel as follows
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional" >
<ContentTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Send mail" onclick="Button1_Click" />
</ContentTemplate>
</asp:UpdatePanel>
You need to use the the POST > Redirect > GET pattern. Here is explanation link
I'm trying to implement in my web form an easy wait function, it works, but not as I would.
My code is this:
for(int i = 0; i<5; i++)
{
Label1.Text = "Invio: " +i;
System.Threading.Thread.Sleep(6000);
}
The problem is that Label Text doesnt' change every 6 seconds.
This script should use 30second and change the label text in this manner:
"Invio: i" every 6 seconds.
Instead it waits 6 seconds and then it change the text in "Invio 4".
Why?
The reason this happens is because of the view state . Before you render your page the back-end code is executed, after it finishes, the DOM start to render and then your page is ready. That means your page won't refresh the label value every N seconds, because it has been already set. If you want to change the value of this dynamically you should use some front-end method as JavaScript or jQuery. If you want this approach - comment so I can make a fiddle for you.
Also this would be helpful for you - ViewState
Here is a fiddle to check if you want something like this - Fiddle demo
var count = 1;
time = setInterval(function(){
document.getElementById("label1").innerHTML="Indio: " + count;
count+= 1;
if (count == 5)
{
clearInterval(time);
}
},6000);
Back end like this:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Timer1_Tick(object sender, EventArgs e)
{
Label txt = Label1;
int i = Convert.ToInt32(txt.Text);
if (i == 4)
{
Timer1.Enabled = false;
}
else
{
i++;
Label1.Text = i.ToString();
}
}
}
and front-end is like this:
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Timer ID="Timer1" runat="server" OnTick="Timer1_Tick" Enabled="true" Interval="6000">
</asp:Timer>
<asp:Label ID="Label2" runat="server" Text="Invio: "></asp:Label>
<asp:Label ID="Label1" runat="server" Text="0"></asp:Label>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Timer1" />
</Triggers>
</asp:UpdatePanel>
</asp:Content>
This will loop 5 times with a 6 second interval.
Timer on page will trigger a postback, server side will execute and will update an updatepanel.
Unfortunately there is no easy way of doing that kind of thing purely using basic Asp.Net webforms (unless you use Asp.Net Webforms AJAX - which I personally find very confusing).
Assuming you are trying to provide some feed back to your user, about a long running operation, I'd use a combination of javascript (using JQuery Ajax for example) and a simple page to poll if the task is done, then redirect to result page.
UPDATE
I moved the Javascript to the ASPX site instead, and added a postback function for it. Now it works. Thanks to #orgtigger and especially #lucidgold for spending their time helping me!
Here is the update code that works!
<script type="text/javascript">
function changevalue(katoid) {
$('#<%=txtboxchosenkat.ClientID%>').val(katoid);
__doPostBack('<%= updpnlgridview.ClientID %>', '');
}
</script>
Code:
<asp:UpdatePanel ID="updpnlgridview" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:TextBox ID="txtboxchosenkat" style="display:none;" runat="server" OnTextChanged="txtboxchosenkat_TextChanged" AutoPostBack="true"></asp:TextBox>
<asp:GridView ID="gridview" runat="server"></asp:GridView>
</ContentTemplate>
</asp:UpdatePane
Code-behind:
protected void hidfldchosenkat_ValueChanged(object sender, EventArgs e)
{
SqlConnection cn2 = new SqlConnection("Server=**,***,***,**;Database=******;
User Id=******;Password=******;");
SqlCommand cmd2 = new SqlCommand("SELECT * FROM tblProducts where KatID='" +
txtboxchosenkat.Text + "'", cn2);
SqlDataAdapter da2 = new SqlDataAdapter(cmd2);
da2.SelectCommand.CommandText = cmd2.CommandText.ToString();
DataTable dt = new DataTable();
da2.Fill(dt);
gridview.DataSource = dt.DefaultView;
gridview.DataBind();
}
The links (only part of code that makes links):
string line = String.Format("<li><a href='#' onclick='changevalue(" + pid + ");'>{0}",
menuText + "</a>");
Old Post
I need to update a GridView based on the value of a HiddenField. I am currently using a button to populate the GridView, but would like to do it automaticaly as soon as the value in the HiddenField changes.
But when I change the value with a javascript, then event doesn't fire.
(Same thing also happens in case of a TextBox and its OnTextChanged event.)
Not sure if this is way it's meant to work.
A Hidden field will not produce a postback (there is no AutoPostBack property), which means no postback will happen when the value of the hidden field has changed. However, when there is ANY postback from the page then OnValueChangd event will execute if a hidden field value has changed.
So you should try the following ideas:
1) Update your JavaScript for changevalue as follows:
function changevalue(katoid)
{
document.getElementById('" + hidfldchosenkat.ClientID + "').value=katoid;
_doPostBack(); // this will force a PostBack which will trigger ServerSide OnValueChange
}
2) Change your HiddenField to a TextBox but set the Style="display:none;" and set AutoPostBack="true":
<asp:TextBox runat="server" ID="hidfldchosenkat"
Value="" Style="display:none;"
AutoPostBack="true" OnTextChanged="hidfldchosenkat_TextChanged">
</asp:TextBox>
This example works great for me:
JavaScript:
function changevalue()
{
$('#<%=hidfldchosenkat.ClientID%>').val("hi");
}
ASPX Code:
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:TextBox ID="hidfldchosenkat" runat="server" AutoPostBack="true"
ontextchanged="hidfldchosenkat_TextChanged"></asp:TextBox>
<asp:Button ID="Button1"
runat="server" Text="Button" OnClientClick="changevalue()" />
</ContentTemplate>
</asp:UpdatePanel>
C# Code-Behind:
protected void hidfldchosenkat_TextChanged(object sender, EventArgs e)
{
string x = "hi"; // this fires when I put a debug-point here.
}
Your issue could be with:
document.getElementById('" + hidfldchosenkat.ClientID + "').value=katoid
You may want to try:
$('#<%=hidfldchosenkat.ClientID%>').val(katoid);
Also you should PUT changevalue() inside your ASPX JavaScript tags and not register it for every LinkButton.... so instead try the following:
protected void lagerstyringgridview_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Assuming the LinkButtons are on the FIRST column:
LinkButton lb = (LinkButton)e.Row.Cells[0].Controls[0];
if (lb != null)
lb.Attributes.Add("onClick", "javascript:return changevalue(this);");
}
}
You can have any event fire by doing a __doPostBack call with JavaScript. Here is an example of how I used this to allow me to send a hiddenfield value server side:
ASPX
<asp:HiddenField runat="server" ID="hfStartDate" ClientIDMode="Static" OnValueChanged="Date_ValueChanged" />
JavaScript
$('#hfStartDate').val('send this');
__doPostBack('hfStartDate');
This will call the OnValueChanged event and cause a postback. You can also set this is a trigger for an update panel if you would like to do a partial postback.
so basically im in a process of creating my unit project which is an eCommerce website. one of the feature that important is a watch list (ex: watch list in ebay)
now i already finish in designing and succeed in adding/removing db record but what bothers me is that the page is the delay/ page posting back for each item saved/clicked. i tried adding an update panel but there is a still delay when we click the button.
below is my copy of the code
Design
<listview>
<itemTemplate>
......
<asp:UpdatePanel ID="UpdatePanel2" runat="server">
<ContentTemplate>
<asp:LinkButton ID="lnkSaved" class="btn-icon btn-white btn-star btn-radius" runat="server" CausesValidation="false" CommandName="ToggleSave">
<span></span>
<asp:Label ID="lblSaved" runat="server" Text="Save Activity" AssociatedControlID="lnkSaved"></asp:Label>
</asp:LinkButton>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="lnkSaved" />
</Triggers>
</asp:UpdatePanel>
.......
</itemtemplate>
</listview>
CodeBehind
protected void ListViewActivities_ItemCommand(object sender, ListViewCommandEventArgs e)
{
HiddenField hdnisSaved = e.Item.FindControl("hdnisSaved") as HiddenField;
HiddenField hdnActivityID = e.Item.FindControl("hdnActivityID") as HiddenField;
LinkButton lnkSaved = e.Item.FindControl("lnkSaved") as LinkButton;
Label lblSaved= e.Item.FindControl("lblSaved") as Label;
Guid userID = new MembershipHelper().GetProviderUserKey(WebSecurity.CurrentUserId);
if (Convert.ToBoolean(hdnisSaved.Value))
{
lnkSaved.Attributes.CssStyle.Clear();
if(Convert.toboolean(hdnisSaved.Value))
{
lnkSaved.Attributes.Add("Class", "btn-icon btn-white btn-radius btn-star");
lblSaved.Text ="Save";
}
else
{
lnkSaved.Attributes.Add("Class", "btn-icon btn-white btn-radius btn-starred");
lblSaved.Text ="Saved";
}
new CustomerDAC().ToggleSave(userID, Convert.ToInt32(hdnActivityID.Value,hdnisSaved.Value));
}
}
could you guys give me a direction, what should i do so a user will have a smooth experience(async prefered) when clicking this button.
You probably want to perform the action on the client side (browser side) in javascript/jquery and then sync the changes in the background, so that the user's perception is immediate but the slow part (http roundtrip to the server and persisting the data to DB) happens in the "background".
In this example I want when the button with ID "PostCommentsButton" is pressed this ContentTemplate to be triggered and to iterate all again in ListView with ID "CommentListView". But this didn't work here. What I miss ?
In this example I take the new text from textfield and in code behind I put this new content from textfield with ado.net and I save this new content in database. The problem is that when the button in UpdatePanel is pressed the new information didn't come in the list with the other content. It comes only if I restart the page. I want ListView in UpdatePanel to be iterated again to take this new content from the textfield with AJAX when the button is pressed. What should I do ?
aspx code:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="PostCommentsButton" />
</Triggers>
<ContentTemplate>
<asp:ListView ID="CommentListView" runat="server" DataSource= '<%# Eval("Comments") %>'>
<ItemTemplate>
<div class="postComments">
<span class="authorComment"><%# Eval("Author") %></span>
:
<span class="commentContent"><%# Eval("Message") %></span>
</div>
</ItemTemplate>
</asp:ListView>
</ContentTemplate>
</asp:UpdatePanel>
code behind :
protected void PostsListView_ItemCommand(object sender, ListViewCommandEventArgs e)
{
//commandName is for recognize the clicked button
if (e.CommandName == "postComment")
{
//get the comment from textbox from current listview iteration
BlogProfileEntities blogProfile = new BlogProfileEntities();
var commentBox = e.Item.FindControl("AddCommentTextbox") as TextBox;
var hiddenFieldPostID = e.Item.FindControl("CurrentPostIDHiddenField") as HiddenField;
string text = commentBox.Text;
var postID = hiddenFieldPostID.Value;
Comment newComment = new Comment()
{
Message = text,
PostID = int.Parse(postID),
Author = Membership.GetUser().UserName
};
blogProfile.Comments.Add(newComment);
blogProfile.SaveChanges();
I dont see a text box in your example. If the text box is not in the update panel that gets called when the list view post back fires, I dont think you'll get the current value. I would suspect that if you put a break point on your commentBox variable, you would see it comes back as Nothing. If this isn't your full code, post everything.