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.
Related
This is a follow up to an earlier issue which I provided my own answer to but there is a new wrinkle in the process that I'm looking for an answer.
Scenario:
Have a asp.TextBox embedded inside of a asp.FormView control. Prior issue was that I couldn't populate the TextBox from code behind (C#). This was corrected by adding AutoPostBack = "true" to the TextBox.
Issue:
The postback corrected the population of the Text box but now two passes on the control assignment have to be executed in order to see the textbox populated.
Specific Question
How can correct this so it doesn't require a second click of the button to see the textbox populated.
Code Examples:
/*-- This is the fragment of code in the aspx which is related to the issue: --*/
<asp:FormView runat="server" ID="EditImpStndPreamble" DataSourceID="ImpStndPreambDS" OnItemCommand="EditImpStndPreamble_ItemCommand" DefaultMode="Edit" DataKeyNames="ARS_Index">
<InsertItemTemplate>
<asp:Label runat="server" Font-Size="Small" Font-Bold="true" Width="60" Text="Index #"></asp:Label>
<asp:Label Text='<%# Eval("ARSEL_Index") %>' runat="server" ID="ARSEL_IndexLabel1" Width="74" />
<asp:Label runat="server" Width="60" Font-Size="Small" Font-Bold="true" Text="Control #"></asp:Label>
<asp:TextBox Text='<%# Bind("ARSControlNum") %>' runat="server" ID="ARSControlNumTextBox" Width="74" />
<asp:LinkButton runat="server" Text="Insert" CommandName="Insert" ID="InsertButton" CausesValidation="True" /> <asp:LinkButton runat="server" Text="Cancel" CommandName="Cancel" ID="InsertCancelButton" CausesValidation="False" />
</InsertItemTemplate>
</asp:FormView>
// This is the fragmentof code in the C# code behind related to the issue
// This is where we update the control number
Label ctrnum = (Label)EditElementsFV.Row.FindControl("ARSControlNumLabel");
if (ctrnum != null)
ctrnum.Text = Session["CurrentControl"].ToString();
Any insight here would be welcomed. I've tried several things but haven't come up with a means of making this work like I want it to. I'm thinking if I could trigger a second postback of only the TextBox control here that could resolve it. The problem is every method of doing a postback from code behind seems to reset the page which by default has this FormView invisible.
Regards,
Updated 03/24/17 1:06PM Central US:
I took a bit of a break from this issue to work on another segment of the project. I tried several more thing but the last thing I did was track several variables through the debugger and examine the flow of the code as I stepped through the pertinent sections of code.
To the double tap issue I discovered that the first time you click on the Insert Implementation Standards button that the execution was routed through 'Item Template' of the FormView and then it ran through the 'Insert Template' before coming to rest.
Conversely the second click of the button executed as I would have expected and ONLY executed the 'Insert Template of the FormView.
I also observed all the variables that are used in the DataSource related to the FormView being properly populated prior to the execuation of either the Item Template and/or the Insert Template of the FormView.
So, this is even more baffling that I originally ran into it because at first all that I was dealing with was the lack of visibility of two TextBoxes, now however, we have the curiosity of the code executing the Item Template of the FormView prior to walking through the Insert Template.
Ken...
Updated: 03/27/17 9:55AM Central US
I have been working on this and searching for examples of similar issues that I might be able to leverage from and so have now attempted using a FormView.ItemInserting block (Which is bypassed prior to actual execution of the 'insert') and FormView.DataBound blocks. The DataBound was able to trigger but I had to encompass the block in a conditional 'if (IsPostBack)' to avoid trigging a null reference error. This properly routed through the block however the result on the screen draw was the same wit the fields not being populated as intended. Here is the last block as last attempted:
protected void EditElementsFV_DataBound(object sender, EventArgs e)
{
if (IsPostBack)
{
Label ctrnum = (Label)EditImpStndPreamble.Row.FindControl("ARSControlNumLabel");
if (ctrnum != null)
ctrnum.Text = Session["CurrentControl"].ToString();
Label famlbl = (Label)EditImpStndPreamble.Row.FindControl("ColumnTagLabel");
if (famlbl != null)
famlbl.Text = Session["CurrentFamily"].ToString();
}
}
Pressing on but could really use some other eyes on this.
Update: 03/29/17 7:42AM Central US
I wanted to post this update yesterday but got pulled off on a different project for a bit. My latest attempt to resolve this issue I thought for certain that it would work. But it has also failed to load the values into the insert mode of the forum until the button has been selected the second time.
What this does is from the trigger of 'DataBound' in the FormView it directes the flow to a function FillDefaultValue which assigns default values to the two parameters that are in the FormView that control the TextBox displays.
In my mind this 'should have' resolved the issue as the default value would then be the values contained in the Session variables instead of being blank(null).
public void FillDefaultValueInFormView()
{
if (EditElementsFV.CurrentMode == FormViewMode.Insert)
{
EditElementsDS.SelectParameters["ARSControlNum"].DefaultValue = Session["CurrentControl"].ToString();
EditElementsDS.SelectParameters["ColumnTag"].DefaultValue = Session["CurrentColumn"].ToString();
}
}
protected void EditElementsFV_DataBound(object sender, EventArgs e)
{
if (IsPostBack)
{
FillDefaultValueInFormView();
}
}
So the mystery continues...
I ended up using the function FillDefaultValueInFormView() defined in the question to resolve this.
I watch in debut the flow over and over again and realized what was happening was that when I set the FormView's mode to Insert that it was flushing the value assignments that I was placing on the TextBox.
Then I realized that what I needed to do was assign the default value in the DataSource to be what I desired in the TextBox 'prior' to setting the mode of the FormVeiw to Insert. So, I added the call to the function in the early portion of my Button_click event immediately followed by changing mode of the FormView to Insert.
protected void AddImpStadBTN_Click(object sender, EventArgs e)
{
Session["CurrentColumn"] = "IMP";
FillDefaultValueInFormView();
EditElementsFV.ChangeMode(FormViewMode.Insert);
... More code follows to complete this but left off as it doesn't effect the results...
}
After doing this the change to insert mode on the FormView was successfully prepopulated as I had intended for the user. I'll now change them to ReadOnly so the user can't change them, making them programmatically driven fields within the form.
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.
I'm building an asp.net cutom control inside which I have two dropdownlists: companyIdSelection and productFamilySelection.I populate the companyIdSelection at Page_Load and in order to populate the productFamilySelection depending on the selected item in companyIdSelection.I'm using UpdatePanels to achieve this, but for some reason every time I update companyIdSelection Page_Load is being called ( which as far as I know should happen only when the entire page is reloaded ), the list is being reloaded again and the item the user selected is lost( the selected item is always the top one ).Here's the code
<asp:UpdatePanel ID="updateFamilies"
runat="server"
UpdateMode="Always">
<ContentTemplate>
Company ID:<br>
<br></br>
<asp:DropDownList ID="companyIdSelection"
runat="server"
AutoPostBack="True"
OnSelectedIndexChanged="companyIdSelection_SelectedIndexChanged">
</asp:DropDownList>
<br></br>
Product Family:
<br></br>
<asp:DropDownList ID="productFamilySelection" runat="server"
AutoPostBack="True"
onselectedindexchanged="productFamilySelection_SelectedIndexChanged">
</asp:DropDownList>
<br>
</ContentTemplate>
</asp:UpdatePanel>
protected void Page_Load(object sender, EventArgs e)
{
this.companyIdSelection.DataSource = companyIds(); //companyIds returns the object containing the initial data items
this.companyIdSelection.DataBind();
}
protected void companyIdSelection_SelectedIndexChanged(object sender, EventArgs e)
{
// Page_Load is called again for some reason before this method is called, so it
// resets the companyIdSelection
EngDbService s = new EngDbService();
productFamilySelection.DataSource = s.getProductFamilies(companyIdSelection.Text);
productFamilySelection.DataBind();
}
Also, I tried setting the UpdateMode of the UpdatePanel to "Conditional" and adding an asyncpostback trigger
but the result was the same.
What am I doing wrong?
PS:
I fixed the updating problem, by using Page.IsPostBack in the Page_Load method, but I would still want to avoid a full postback if possible
I think you misunderstand how UpdatePanels work. They DO actually do a full page postback, it's just that during the rendering stage they capture only a portion of the output and send it back in the AJAX response so the page can be updated. More info here.
So you will still need to check whether it is a postback in your page_load event and only perform your data load if it isn't one.
The update panel call back will go through the page load on every call back. In face, the pull page lifecycle (minus render and prerender) will occur. Update panels give the appearance of ajax, but your client side code still posts back to the same page - which is the problem you are describing. If you can avoid using Update Panels, I suggest you do so. Use something like jQuery instead. If not, then use this in your Page_Load
if (Page.IsCallback) { } //Do callback specific code here
else { } //Do Postback specific code here
Hope this helps. Good Luck.
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
}