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
}
Related
I am using GridView control for uploading files I am uploading using RowCommand Event, My scenario is like this
User login and comes to the page and upload file
User login, enter some data and save it,post back will occur and data will be shown in Grid.
The Upload functionality is working fine in scenario 1, however its not working after scenario 2
This is my Code
<asp:GridView ID="GVUsers" runat="server" OnRowDataBound="GVUsers_RowDataBound" OnRowCommand="GVUsers_RowCommand"
OnRowDeleting="GVUsers_RowDeleting" AutoGenerateColumns="false" CssClass="table">
<Columns>
<asp:TemplateField HeaderText="Files" ItemStyle-HorizontalAlign="Left">
<ItemTemplate>
<asp:FileUpload ID="filedoc" runat="server" Width="98%" CssClass="filedoc" />
<asp:Button ID="btnuploadfiles" runat="server" CommandName="fileupd" Text="Upload"
CssClas="uploadbtn" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
protected void GVUsers_RowCommand(Object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "fileupd")
{
//Upload File
}
}
and this is how I am databinding
if(!Page.IsPostBack)
{
//Assigning datasource and DataBinding
}
I also tried binding grid after the above condition,ie Binding Grid always,but no Luck
I tried assinging event handler from code behind,but same issue.
Also on Save Button I am doing this after saving
protected void btnsave_Click(object sender, EventArgs e)
{
//Assigning datasource and DataBinding
}
as per I investigated the problem is in btnsave_click, but if I use only
GVUsers.DataBind() it will not show newly added records in the Grid.
I also have tried by disabling ViewState of the Grid.
I am databinding Grid with DataTable
How can I make RowCommand Working after post back or how can I re databind grid after post back?
Why don't you save the user entered data via ajax call and refresh the page later.. it would help you avoid the post back call
here is some change you need to
when your page load first time bind gridview on page load event
if(!Page.IsPostBack)
{
//Assigning datasource and DataBinding
}
but when you call again GVUsers.DataBind() you need to re-assign datasource again with updated record
make sure your grid view not in update panel beacause if you use update panel you can't get uploded file at server side
Sometimes, grid views's RowCommand event stops firing.
One solution that you can try is re-binding your grid every time your pages posts back i.e. move the grid binding logic out of the if(!Page.IsPostBack) condition.
You will see that the RowCommand event will now fire successfully. The problem with this solution is that you will lose any data captures within your grid e.g. data in text fields in rows. If you don't have this situation, then this solution is safe.
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";
}
}
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','')
I have an asp:GridView control inside a .aspx page that the user can add several rows of data to. The user must also be able to attach a file to each row of data added.
For this I use the following inside the GridView:
<asp:TemplateField HeaderText="Upload" HeaderStyle-Width="120px">
<EditItemTemplate>
<asp:FileUpload ID="fuUploadLocation" runat="server" Width="98%" TabIndex="18" />
</EditItemTemplate>
</asp:TemplateField>
Then to save the location of the file upload I use the RowUpdating event in code-behind to set the value etc.
The problem is I can't register a PostBackTrigger for the control on the html as it doesn't pick it up as it's inside the GridView. I've tried setting it dynamically from other examples but can't seem to get this to work, the result being my FileUpload's FileName is always empty and the file then doesn't save correctly.
Any suggestions would be awesome.
Thanks
On Gridview row databound you have to find the file upload control and then add it to your UpdatePanel postback trigger.
I've not found a solution to my problem but I did work around it (sort of). I know just add a link to the grid, when user clicks it sends ID through via querystring, a new page opens that handles the entire upload process and returns the url of the saved document.
Not ideal but it works and saved me hours of frustration.
In the OnItemDataBound event handler of the grid need to call ScriptManager.GetCurrent(this).RegisterPostBackControl(ControlID);
This is an old post but for anyone that is stuck with it, you need to add the following to your control as stated in the other answers.
protected void ItemDataBound(object sender, EventArgs e)
{
Button myButton = (Button)e.Item.FindControl("myButton");
if (myButton != null)
ScriptManager.GetCurrent(Page).RegisterPostBackControl(myButton);
}
You also need to change the enctype in your form tag to the following e.g.:
protected void Page_PreRender(object sender, EventArgs e)
{
Page.Form.Attributes.Add("enctype", "multipart/form-data");
}
It should then work without an issue.
In an ajaxified RadGrid I want two buttons to cause a postback (bypass Ajax) and execute some back-end code. Here's what I have so far...
Buttons (just showing one for simplicity):
<telerik:GridTemplateColumn HeaderText="Actions">
<ItemTemplate>
<asp:ImageButton ID="btnEdit" runat="server" OnClientClick="realPostBack();" ImageUrl="~/images/icon_edit.png" style="display: inline-block" ToolTip="Edit" CommandName="fbEdit" />
</ItemTemplate>
</telerik:GridTemplateColumn>
Javascript function I'm using to disable the postback:
<script type="text/javascript">
function realPostBack(eventTarget, eventArgument) {
$find("<%= RadAjaxPanel1.ClientID %>").__doPostBack(eventTarget, eventArgument);
}
Code-behind I want to execute:
protected void RadGrid1_ItemCommand(object sender, GridCommandEventArgs e)
{
if (e.CommandName == "fbEdit")
{
//grab variables from row's cells
string userID = e.Item.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["UserID"];
string userName= e.Item.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["UserName"];
string userEmail = e.Item.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["UserEmail"];
//DO SOME PROCESSING STUFF
}
if(e.CommandName == "fbDelete")
{
//delete record
}
}
So the post back does indeed occur, but my code never fires. I'm guessing it's because the event is tied to the grid and not to buttons im "un-ajaxifying", but I went this way because I NEED to capture the values of some of the cells in the row that the button was clicked.
Maybe I can rework this to use the buttons onClick Event, but I would still need to capture those values.
Can anyone help?
From the look of things you are attempting to execute code in the OnItemCommand event of the RadGrid, but it seems like you might be making things a bit over-complicated. Why not use a GridButtonColumn, set the ButtonType to ImageButton and then set the same CommandName as you do above? As long as you're subscribing to the OnItemCommand event this should trigger everything to get called and your conditional check for e.CommandName == "fbEdit" should be hit as well.
For an example of how to use this RadGrid specific column (in a similar manner) you can check out this demo.
In you need to add bellow code in PageLoad Event.
if (!IsPostBack)
{
RadGridName.Rebind();
}
thats it.