Im working on asp.net with c#.
I have a gridview with templatefield columns, data comes from an sql database. I have linkbutton on the item template, the linkbutton calls the Rowediting event to enable the editing. This works fine on the first row. But when I click on any of the other rows nothing happens, the event never gets fires.
How can I solve this?
Thanks..
Most likely you are data-binding the grid in the Page_Load event. If this is the case, the ASP.NET Page Lifecycle is getting in your way. (Be sure to read the article in the link provided. Every .NET developer needs to know about the Page_Lifecycle. It explains a lot of behavior thaqt would otherwise cause confusion, such as this behavior.)
The Page_Load event happens on every postback - every button click, or any event that triggers the postback.
If this is the case, there are two possible options:
Move your data binding code to Page_Init
Put your data-binding in Page_Load inside an if(!Page.IsPostback) block.
In essence, the problem is that your page is data-binding on the first load.
Then the editing event is triggered by some client action, which triggers a postback. In this postback, Page_Load fires first, which re-binds the GridView, erasing all of the data that was associated with it on the previous load. So when the RowEditing event fires (control events always happen AFTER Page_Load) there's nothing for it to do. All references to the data as it existed before postback are gone.
If you move your binding code too Page_Init, you can get around this because the page will be bound, and then all of the Viewstate will be re-applied to it, restoring the data that was lost in the postback in the scenario above.
Related
I have a data grid that is created dynamically to display information retrieved from a database. The data grid consists of multiple bound columns and two button columns for each row, a view and a delete button.
Clicking either button calls the Page_Load() method with Page.IsPostBack as false.
if (!Page.IsPostBack)
{
this.bindForm(); // Populates drop down lists that the user can select
setAccess(false); // Sets access for the page
// Stuff commented out to avoid confusion
}
else
{
bindDynamicGrids(); // Create the data grid(s) and populate them
}
So when I first click the button the above code gets called with IsPostBack false, and the dynamic grids get bound. But, the button click event does not fire. When I click the button a second time, Page_Load is called with IsPostBack false, and after executing bindDynamicGrids() the button click event is fired. I cannot understand the difference between the first and second click.
I have read a few threads;
ASP.NET C#, need to press a button twice to make something happen
http://forums.asp.net/t/1783694.aspx?ASP+NET+Button+needs+to+be+clicked+twice
To attempt to understand the issue, but I must be missing something. From what I am gathering from the second link, a session variable may be getting set in the click event, which is also being set in Page_Load, and this is all an issue with ordering. If that is the case I am not seeing where it is happening.
When it is not a post back the bindForm() method is called, which populates all drop down lists. The edit click event populates those drop downs with the values from the row, but the click event is always a post back and the form has already been bound.
I have also considered having a script automatically double click one of the buttons anytime the user single clicks, but I have not been able to find an "OnClick" property for the column button. Any help that could be provided would be phenomenal.
The thing is, that the button click event happens after the Page_Load event meaning that the filtering does not get applied on the first postback. It has been updated on the second postback and you see the filtering.
You can try to move the code of your page_load event to OnPreRender so the reload happens after the button click event.
for more information look here: Button needs to be clicked twice
and here
Alright so in the project I am working on I am making a hard coded asp:panel on the page and then filling it with:
A Drop Down list
An asp:Table, with an asp:TableHeaderRow
Add and Cancel Buttons
When the selectedIndexChanged event happens with the DropDownList the tablerow gets created then filled with 6 or so tablecells which then get asp:Textboxes placed inside of them.
Eventually they all get added to the tablerow which then gets added to the tablerowcollection.
That all works just fine,but when I go to add the information from these dynamically created TableRows with a foreach loop they are no where to be found but the TableHeaderRow is.
Also when I click add and let it go through the process I get no null exceptions and the only thing left after it is the header, all my rows disappear.
Anyways I feel that I am just missing something really dumb. I've looked through a lot of forums, posts, MSDN and never found an answer to my problem. Any help would greatly be appreciated!
You need to add your dynamic rows to your Table in Page_Init not Page_Load. If you are creating it in Page_Load your new rows won't be added to ViewState and you will see this problem.
Unfortunately you are adding them in response to a server side event which can get tricky. You still need to add the rows in Page_Init but when the page posts back and you at in Page_Init then the selectedIndexChanged event hasn't yet fired. It's too early in the page lifecycle.
If you want to know if it has fired at Page_Init the only way I have found is by examining Request.Form("__EVENTTARGET") collection at that point. This contains the control ID of the control that has triggered the postback - in your case this will be the dropdown list. The control that fired the event will be there but the ID will be qualified i.e not MyControID but ctl_MasterPageContentHolderID_NamingContainer1_MyControlID` or the like - so you will have to take it into account when looking for it. Once you have identified that that event has fired then you can add the rows. Once they are added there then they won't disappear.
As I say it is tricky to get working but I have done this successfully in the past. Generally dynamic controls can be very hard to work with for just this reason. You may want to consider alternatives. Best of luck with it anyway though.
I'm trying to bind my GridView at runtime, but I'm also trying to avoid running all the binding events twice.
I have a GridView that gets populated from a function that returns a DataTable. I'm not using ViewState in the grid for a couple of reasons. I seem to have a Catch-22 situation here:
If I don't bind the grid by Page_Load at the latest, the RowCommand and other grid events won't fire.
If I DO bind the grid in Page_Load, but I'm on a PostBack from a pager link, sort link, or search button, those event handlers will change the data and need to rebind it, running all the binding code again.
The grid triggers DataBound, RowDataBound, and RowCreated events, which could be performing expensive operations. I really hate to call them all in Page_Load, and then wipe out the data and call them all again if the data changes. But I can't seem to avoid this double duty, because in Page_Load I don't know if it was a grid event that will change the data, or a grid event that doesn't.
Any ideas?
Try the command arguments. If a button in the gridview was clicked, that event will be fired and you can handle it appropriately. Your question is not clear enough i'm afraid. Could you be more specific?
Check if request is a postback. Bind the datatable to the grid like so:
If(!ispostback)...
That way you wont be binding the table to the grid on each request.
I have a question about button inside the gridview. As the title says, I designed a gridview with a button inside. Whenever I trigger the button, it always binding the gridview before it can reach the button event.
Say, onLoad page, I pull data and bind them to a gridview, then I would like to do a mass update which will be triggered by the button inside it. If i put !IsPostBack, it never triggers the button event, which means it always has to read the data bind them into gridview again then execute the button event.
Problem is, I have a huge data and it takes much time to update because of it. I am wondering if there are any ways to trigger the button event without rebinding the gridview again? Is it because of the button inside the gridview so it is necessary to rebind again before it could read the button event?
Any suggestion would be really appreciated.
Why don't you use the RowCommand instead of the onclick event?
you can add a command name property to the button to understand what operation you need to do
Have a look at the link below and just replace the ButtonField with a classic button. don't forget to assign a CommandName
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridviewcommandeventargs.aspx
You should not use the button event, but the GridView.RowCommand event instead. See here. If you do this in combination with the if (!IsPostBack) check in Page_Load, it should work for your scenario.
your button must be triggered by OnRowCommand event and ! IsPostBack shouldn't prevent triggering your button
protected void GridView_RowCommand(object source, GridViewCommandEventArgs e)
{
if(e.CommandName=="Update")
{
// put your update code here
}
}
and you can use ajax to update your datasource without rebinding your GridView and update your UI using javascript.
On an ASP.NET page, I have a GridView populated with the results of a LINQ query. I'm setting the DataSource in code, then calling DataBind on it. In the GridView's RowDataBound event, I'm selectively hiding links in some GridView fields based on the query results. (For instance, I hide the "Show Parent" link of the row in question has no parent row.)
This works fine initially. But on postback (when I don't call DataBind, but the GridView stays populated through ViewState), the data displays, but the RowDataBound event (obviously) doesn't fire, and my links don't get hidden.
What's the best way to get the links to be hidden after a postback?
The RowDataBound event only fires when the GridView's data changes during the postback. The event is short-circuited for speed so it's not re-generating the exact same data unnecessarily. Use the RowCreated event to manipulate the HTML instead - it fires on every postback regardless of whether the data has changed.
Here's how I ended up solving this:
I created a serializable class with readonly properties: PK of a row, and a boolean for each link indicating whether it's enabled or not. We'll call it LinkVisibility.
I created a serializable class inheriting from KeyedCollection to hold instances of the class above.
I created a ViewState-backed property holding an instance of that collection.
In my Search procedure (populating the GridView), I clear the collection.
In RowDataBound, which initially shows/hides the links, I add a LinkVisibility instance to the collection for each row.
In Page.Load, when IsPostBack is true, I loop through the GridView rows. I look up the LinkVisibility for each one by PK in the collection (DataKeyNames is set in the GridView), and I set the links accordingly.
I don't know that this is the best way to do this, but it certainly does work, which is more than I can say for anything else I've tried.
1) You could have a Method - ProcessDataRows() that would get called once on grid_DataBound(...). And then when you need it after PostBack.
And that way you process all rows when you want.
2) You could have methods like ShowParentLink(). That are then bound to the LinkButton in the grid (if you're using an ItemTemplate) and the link would have
Visible='<%#ShowParentLink()%>'
I would have expected the viewstate to also reflect the fact that you have removed some of the links (assuming that they were removed before viewstate was saved).
Maybe thats the question you need to ask 'why do the removed links still appear in viewstate?'.
Another solution is to put the logic in the LINQ query, so that you end up with a boolean LINQ field like "ShowParentLink". Then you can just bind the Visible property of the HyperLink field to that value - no RowDataBound required.
protected void btnHazardRating_Click(object sender, EventArgs e)
{
gvPanelRole.RowDataBound += new GridViewRowEventHandler(gvPanelRole_RowDataBound);
gvPanelRole.DataSource = dtGo;
gvPanelRole.DataBind();
ModalPopup.Show();
}
void Process Rows()
{
... do something
... process complete
datagrid.DataBind();
}
A page cannot process postback events unless it is rebuilt exactly as it was before (the postback). If you re-hide your links during the page-init, then your click events and such should fire. Unfortunately, without seeing some sample code I can't get more specific.
Also the data RowDataBound does not fire because you are not data binding. You are rebuilding the page from the viewstate- "viewstate binding" for lack of a better word.