This probably looks like a duplicate but I don't think so. I have already searched stackoverflow, may be not enough.
Here is my challenge:
<asp:LinkButton runat="server" ID="DeleteRow" CommandName="deleterow"
CommandArgument='<%# Eval("ID") %>' Text="Delete"
OnClientClick="return confirm('Are you sure you want to delete this record?');" />
If you click the link the first time, OnRowCommand is not fired. When you click it the second time, it works.
I looked at the source and I have these differences.
//When you first load the page: the GUID is the PK for that row
1. javascript:__doPostBack('ctl00$content$gvSchoolClasses$58fd1759-f358-442e-bf73-2e9cedfc27e8$DeleteRow','')
//After the link was clicked the first time, the link changed and the ID empty, but works
2. javascript:__doPostBack('ctl00$content$gvSchoolClasses$ctl02$DeleteRow','')
I copied the two codes from the href of the asp:LinkButton for BEFORE and AFTER click.
What is wrong? I only have one other event on my page RowDataBound.
protected void gvSchoolClasses_RowDataBound(object sender, GridViewRowEventArgs e)
{
e.Row.ID = Guid.NewGuid().ToString();
}
protected void Page_Load(object sender, EventArgs e)
{
CheckAuthentication();
if (!Page.IsPostBack)
{
ClassesAcademicYearLabel.Text = "- Year " + Setting.Year;
//FillClassesList(); //filling some combo boxes. Have checked the codes here too
//FillLettersList(); //they didn't affect the Grid
FillGrid();
}
ClassErrorLabel.Visible = false;
}
By setting the ID property of the row in the RowDataBound event, you've created the problem you're observing.
Since the RowDataBound event isn't fired until after the page's controls have already been added to the collection, ASP.NET doesn't have a way to update the already-computed client references. Hence, the command doesn't get fired in the way you're expecting.
I've noticed that you're already setting the CommandArgument property to the ID generated in the RowDataBound event, which could also be part of your problem (depends on order of events firing; I don't have a pipeline chart handy).
EDIT: a quick fix for this could be to simply set the ClientID properties (sorry, not the exact name, but intellisense should get you the rest of the way to it) to some sort of Manual, not Auto determination. That way, the ID you set is never changed by the framework.
To elaborate a bit more on why you're seeing this problem, consider the client-side id's presented:
ctl00$content$gvSchoolClasses$ctl02$DeleteRow
This ID is guaranteed to be unique (for this page) by taking the declared ID (DeleteRow) and successively walking UP the control hierarchy and prepending parent ID's to the string. JS code can be confident that passing this string to getElementById will behave in a consistent, predictable manner.
In order to be able to generate said ID, all of the controls in the hierarchy must already be present and accounted for by the rendering engine.
Now let's consider what happens when that the ID property of a control is changed (note this is not the ClientID, but simply the property with a name of ID).
ctl00$content$gvSchoolClasses$58fd1759-f358-442e-bf73-2e9cedfc27e8$DeleteRow
You'll note that instead of the row's naming container (cl02), it now has the GUID you generated and assigned to it. Client JS attempting to access this container using the previously assigned ID will be disappointed, since it will no longer work as expected!
When an ASP.NET control fires a post-back via a call to javascript:__doPostBack('ctl00$content$gvSchoolClasses$58fd1759-f358-442e-bf73-2e9cedfc27e8$DeleteRow','')
the post-back will occur just fine and dandy, but (and you can verify this by inspecting the form params of the postback) when the server processes the request, it will attempt to rehydrate (from viewstate) a control that doesn't exist. Consequently, it will create a new instance of the control (with the correct ID) which has no idea that a command has been issued, so the XXXCommand event(s) are never fired. Since databinding isn't happening (it's a postback, and your code correctly checks for that condition), the ID is never reset, and the command can be fired normally
don't change the Row.ID in your RowDataBound event. Either change a different value in the grid or just do this in your gridview markup:
CommandArgument='<%: Guid.NewGuid.ToString(); %>'
If you wanted to do it in code behind you could do something like this:
protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
{
LinkButton deleteRow = (LinkButton)e.Row.FindControl("DeleteRow");
if (deleteRow != null)
deleteRow.CommandArgument = Guid.NewGuid().ToString();
}
You need to set the Row Index to the CommandArgument of the Link Button not the guid
As you said it work in the second time but the html is as shown below
//After the link was clicked the first time, the link changed and the ID empty, but works
2. javascript:__doPostBack('ctl00$content$gvSchoolClasses$ctl02$DeleteRow','')
Related
I am attempting to write the selected values to two separate text boxes named this.txtTextSelected.Text = text; and this.txtValueSelected.Text = value;
My issue is that the values are not written to the two text boxes, and when an option is selected my page refreshes and doesn't actually store the selected value which makes me think
1) Either my HTML for the drop down list is incorrect
2) I have added un-needed syntax for something
But I am scratching my head as to what the real deal is.
This is my HTML for the drop down list
<asp:DropDownList ID="dropdownlist1" CssClass="DropDownLists"
runat="server" Width="90px"
AutoPostBack="true"
OnSelectedIndexChanged="dropdownlist1_SelectedIndexChanged">
</asp:DropDownList>
And this is my C# code behind for the page
protected void dropdownlist1_SelectedIndexChanged(object sender, EventArgs e)
{
string value = dropdownlist1.SelectedValue;
string text = dropdownlist1.SelectedItem.Text;
this.txtValueSelected.Text = value;
this.txtTextSelected.Text = text;
}
EDIT
Will this remedy my problem (basing this off #David comment below)
if (!IsPostBack)
{
BindDropDownList();
}
(In response to comments and the question edit...)
Unlike WinForms, WebForms "form" objects don't persist in memory. Web applications are designed to be inherently stateless. So every request results in re-instantiating the targeted form object, which invokes all of the start-up stuff that happens in a form.
This includes Page_Load.
So any time you click a button or do anything that involves posting the page back to the server, Page_Load (and other initialization events) happen again, before any event handlers or custom logic.
This means that if you're binding your controls in Page_Load, you're going to re-bind them before you try to use them. In WebForms, the standard fix for this is to wrap them in a conditional when binding:
if (!IsPostBack)
{
// bind your controls
}
This will bind the controls when initially loading a page, but not when re-submitting the page's form to the page (posting back).
I have a web form that allows the user to modify data in certain fields (mostly TextBox controls, with a couple of CheckBox, DropDownList, and one RadioButtonList control) with a submit button to save the changes. Pretty standard stuff. The catch is, I need to keep track of which fields they modified. So I'm using ASP.NET HiddenField controls to store the original value and then on submit comparing that to the value of the corresponding TextBox (for example) control to determine which fields have been modified.
However, when I submit the form and do the comparison, the value of the TextBox control in the code behind still reflects the original value, even though I have changed the contents of the TextBox, so it isn't registering the change. Here is an example of a set of TextBox/HiddenField pairings (in this case last, first, middle names) in my ASP.NET form:
<div id="editName" class="editField" style="display: none">
<asp:TextBox ID="tbxLName" runat="server" class="editable"></asp:TextBox>,
<asp:TextBox ID="tbxFName" runat="server" class="editable"></asp:TextBox>
<asp:TextBox ID="tbxMName" runat="server" class="editable"></asp:TextBox>
<asp:HiddenField ID="hdnLName" runat="server" />
<asp:HiddenField ID="hdnFName" runat="server" />
<asp:HiddenField ID="hdnMName" runat="server" />
</div>
I'm setting the original values of all these controls (".Text" for the TextBox controls, ".Value" for the HiddenField controls) on PageLoad in the code behind.
Here's an example of where I'm doing the comparison when I submit the form (I'm adding the field name, old value, and new value to List<string> objects if the values differ):
if (tbxLName.Text != hdnLName.Value)
{
changes.Add("ConsumerLastName");
oldVal.Add(hdnLName.Value);
newVal.Add(tbxLName.Text);
}
But when I enter a new value into the TextBox control and click Submit:
then step through the code in the debugger, it shows me that the value of the control is still the old value:
Why is the comparison happening against the original value of the TextBox even though the new value is there when I click the submit button?
Update: #David gets the credit for this, even though he didn't post it as an answer -- I was forgetting to enclose the method for pre-filling the original values of the controls in a check for IsPostBack; I really should have known better, I've been doing this for quite a while!
Are you checking for IsPostback in Page_Load so you don't overwrite the values sent in the Postback?
Make sure that you are not overwriting your values in the Page_Load method:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
someTextField = "Some Value";
}
}
It took a while for me to get that the Page_Load method works as an "before anything goes" method and not only a method that is being ran when you visit the page with GET.
Make sure you're not overwriting the value for the textbox somewhere in page init or load without checking for the IsPostback flag.
It may happen due to postback. If you code for set textbox not in !isPostBack then put it.
i.e.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
tbxLName.Text="anything";
}
}
I have a aspx Page where I am using AJAX. like
<asp:UpdatePanel runat="server" ID="upPanelDDLProgram">
<ContentTemplate>
<asp:DropDownList ID="DDLProgram" runat="server" Width="194px" Height="18px" OnSelectedIndexChanged="OnDDLProgramChanged" AutoPostBack="true">
</asp:DropDownList>
</ContentTemplate>
</asp:UpdatePanel>
and my code behind is like
protected void Page_Load(object sender, EventArgs e)
{
//if (!IsPostBack)
//{
// BindProgramDDL();
//}
BindProgramDDL();
}
protected void BindProgramDDL()
{
List<CcProgramEntity> programEntities = FormSaleSubmit_BAO.GetAllPrograms();
DDLProgram.DataSource = programEntities;
DDLProgram.DataTextField = "Shortname";
DDLProgram.DataValueField = "Id";
DDLProgram.DataBind();
string programCode = programEntities[DDLProgram.SelectedIndex].Code;
}
protected void OnDDLProgramChanged(object sender, EventArgs e)
{
List<CcProgramEntity> programEntities = FormSaleSubmit_BAO.GetAllPrograms();
string programCode = programEntities[DDLProgram.SelectedIndex].Code;
}
the If condition is the page load event, is commented out. If I toggle the comment part of the page load event, it works perfect in both cases. My question is why is this heppening?
IsPostBack tells you if it is a second request to the page. The benefit here is if you need to do anything costly, such as a database call to fill a dropdownlist or similar, you can do it when !IsPostback, then use ViewState to retain the values.
To put it specific to your situation
Using:
if (!IsPostBack)
{
BindProgramDDL();
}
Will result in BindProgramDDL being called ONLY on the first time the page is loaded, all AJAX or other user interaction with the page will NOT call BindProgramDDL;
Without that, in place EVERY page load would call the method, un-necessarily hitting the database for the records.
If I am getting you correct .......
DropDown list has data even you are not binding it second time after post back..........its becasuse its server side control and each serverside control has its view state with it thats y its not removing data.
IsPostBack - it true when do the post back by using serverside control like dropdown, checkbox , textbox............When you load page first time this property is false but in subsequent request to same page value of this property is true. you can check msdn document for more detail about it.
It's basically saying are you visiting the page for the first time (not a post back), or has the user clicked on a control (a post back).
Useful for when you only want to run methods once when the page is initially loaded
You're code should probably look like this to achieve best results
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindProgramDDL();
}
}
I suspect that the DropDownList saves the items in the ViewState and then work with them during all subsequesnt requests. That is why your code works even if the editor's DataSource is set only when IsPostBack returns false.
PostBack event appears on every action (ajax too), except of first page load.
Page.IsPostBack
indicates whether the page is being rendered for the first time or is being loaded in response to a postback.
see http://msdn.microsoft.com/en-us/library/system.web.ui.page.ispostback.aspx
Since you've bound your datasource the first time the page was loaded, the data are still in the viewstate and you don't need to update the control (unless the datasource has changed).
Take also into account that, since you're using ajax, you may also want to intercept if there was an 'asynchronous postback'.
See http://encosia.com/are-you-making-these-3-common-aspnet-ajax-mistakes/
I'm working with a legacy project in C# (.NET 2.0). In this project there are two validationgroups. One for custom login control and one for users to submit to a newsletter. The problem I ran into is that when a user submits to subscribe to a newsletter some custom code is triggered in the page_prerender() method which only should be triggered when a user tries to login.
I have been looking for a solution to recognize which of the two groups is used on postback so I can ignore the custom code when needed. My idea was to try and check which of the two validation groups is being used to validate. Unfortunately after spending a fruitless few hours on google I've not been able to find anything to let me know how to actually known which validationgroup is used when validating. Is there any way to find out?
<asp:Button ID="btn_newsletter"
runat="server"
Text="Verzend"
ValidationGroup="newsLetter"
meta:resourcekey="bnt_newsletter"
OnClick="handleNewsLetter"
CssClass="roundedButtonBig"
/>
<asp:Button ID="LoginButton"
runat="server"
CommandName="Login"
Text="Inloggen"
ValidationGroup="lgnUser"
meta:resourcekey="LoginButtonResource1"
CssClass="roundedButtonBig"
/>
The following code should only trigger when the LoginButton is pressed and it needs to be done on Pre_render(). Or alternatively pass the correct ValidationGroup (where now null is passed).
protected void Page_PreRender(object sender, EventArgs e)
{
//Register custom ValdiationErrorService added errors to JavaScript so they can be added into the popup.
ValidationErrorService.RegisterServerValidationMessageScript(Page, null);
}
to check which validation group is valid, call:
Page.Validate(“newLetter”);
then check
Page.IsValid;
this will return the value. Scott Gu has more on his blog
edit you are also wanting to know which button was clicked within the prerender event it sounds like as well. While you can't find that out from the parameters passed into the page prerender, you can rely on the button events occuring prior to the page_prerender event. within the aspx pages code behind, create a member variable. this variable will be used to denote if the prerender logic should be executed.
next, within the click events of the two buttons, set that local variable to denote if that button should fire the logic you want in the page_prerender event.
last, check your local variable within the page_prerender method, and encapsulate your logic within an if statement based upon your new member variable.
Happy Trails!
I'm presenting information from a DataTable on my page and would like to add some sorting functionality which goes a bit beyond a straight forward column sort. As such I have been trying to place LinkButtons in the HeaderItems of my GridView which post-back to functions that change session information before reloading the page.
Clicking my links DOES cause a post-back but they don't seem to generate any OnClick events as my OnClick functions don't get executed. I have AutoEventWireup set to true and if I move the links out of the GridView they work fine.
I've got around the problem by creating regular anchors, appending queries to their hrefs and checking for them at page load but I'd prefer C# to be doing the grunt work. Any ideas?
Update: To clarify the IDs of the controls match their OnClick function names.
You're on the right track but try working with the Command Name/Argument of the LinkButton. Try something like this:
In the HeaderTemplate of the the TemplateField, add a LinkButton and set the CommandName and CommandArgument
<HeaderTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CommandName="sort" CommandArgument="Products" Text="<%# Bind('ProductName")' />
</HeaderTemplate>
Next, set the RowCommand event of the GridView
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "sort")
{
//Now sort by e.CommandArgument
}
}
This way, you have a lot of control of your LinkButtons and you don't need to do much work to keep track of them.
Two things to keep in mind when using events on dynamically generated controls in ASP.Net:
Firstly, the controls should ideally be created in the Page.Init event handler. This is to ensure that the controls have already been created before the event handling code is ran.
Secondly, you must assign the same value to the controls ID property, so that the event handler code knows that that was the control that should handle the event.
You can specify the method to call when the link is clicked.
<HeaderTemplate>
<asp:LinkButton
ID="lnkHdr1"
Text="Hdr1"
OnCommand="lnkHdr1_OnCommand"
CommandArgument="Hdr1"
runat="server"></asp:LinkButton>
</HeaderTemplate>
The code-behind:
protected void lnkHdr1_OnCommand(object sender, CommandEventArgs e)
{
// e.CommandArgument
}