How do I get dynamically added ASP.NET buttons to fire events? - asp.net

This is probably a simple question but I am not an ASP.NET developer and I am quite stuck.
I have a simple search routine that returns between zero and several hundred results. Each of these must be added to the page as a button and I want to set the text of the button and the CommandArgument property so that when the button is clicked I can read the CommandArgument back and react accordingly.
However, when I click the button the event does not run at all. How can I get it to run?
The code for building the button list (simplified for readability) is as follows:
foreach (SearchResult sr in searchResults)
{
Button result = new Button();
result.Text = sr.name;
result.CommandArgument = sr.ID.ToString();
AccountSearchResults.Controls.Add(result);
result.Click += new EventHandler(SearchResultClicked);
AccountSearchResults.Controls.Add(new LiteralControl("<br/>"));
}
At the minute to test, I have popped a label on the form to put the CommandArgument in. This code is never executed though.
void SearchResultClicked(object sender, EventArgs e)
{
Label1.Text = ((Button)sender).CommandArgument;
}

You mentioned in another answer that you are adding these when a button is clicked. Looking at your code, I would suggest that you try setting a unique ID for each button added, then ensure that on loading the page that buttons with the same IDs and CommandArgument values are reloaded. When a dynamically loaded button is clicked, it must still exist on the page after postback for the event to fire.
I think the ID is all you need, plus your requirement for the CommandArgument). You could put the ID information in the ViewState if you can't get it repeat without a long search process.

Where are you adding this buttons?
if you are adding them inside another control then the event might be raising in the parent control. This happens on DataRepeaters and DataGrids for example.

I think you need to use the OnCommand event handler, rather than the OnClick i.e. try changing this:
result.Click += new EventHandler(SearchResultClicked);
to this:
result.Command += new EventHandler(SearchResultClicked);
UPDATE
Try changing the type of second argument to your event hander from EventArgs to CommandEventArgs. You might also have to set the CommandName property on your button i.e.
result.CommandName = "foo";

Related

AsyncPostBackTrigger not firing on load of user control

I have an update panel which refreshes a user control. The update panel is set to conditional, and the condition is on a textbox control. Using AsyncPostBackTrigger, to fire when the text changes in the textbox, it works fine. However, what I am not getting is when the page is first loaded, and the textbox is populated with data is that it is not firing the postback trigger.
Is there a way of forcing it fire when the page is loaded for the first time?
I have tried simple things such as UpdatePanel.Update(), or txtbox.text = string.empty to force it to recognise a change- but no luck.
Any ideas anyone?
Thanks
Please replace with your ids
private void tb_Loaded(object sender, RoutedEventArgs e)
{
TextStateChanged((TextBox)sender);
}
UpdateSite.txtPhone.Loaded += new RoutedEventHandler(tb_Loaded);

Best way to allow postback on a gridview without viewstate

My gridview is basically a hit list of results from which the user selects one, and I want to get a postback saying which one he has selected. There is no need for the grid contents to survive the postback round-trip because the hit list disappears as soon as he has selected an item.
I don't want to use viewstate because the hit list is likely to be large. I don't want to databind from the database in PageLoad to repopulate the grid because the search may take a while.
what I'm thinking at the moment is that I can put some javascript on the 'select' link to store the ID of the selected item in a hidden field and then call __doPostBack
this still seems a bit clunky. can you think of a cleaner way?
If the postback should be triggered when the user clicks the anywhere in the row, use the ItemDataBound event to attach a client onclick handler:
protected void GridView1_ItemDataBound(object sender, GridViewRowEventArgs e)
{
var dataItem = e.Item as GridViewRow;
if (dataItem != null)
{
dataItem.Attributes["onclick"] = string.Format("__doPostBack(this, '{0}')", e.Row.RowIndex);
}
}
Is the ID of the selected item something sensitive that should not be seen by the user?
If it is not, you could just make your select button a link to the next page, with the ID as a querystring variable. Clicking would just move to the next page, no postback required.

asp:DataPager onclick event

I am working with the .Net List view along with a data pager to enable pagination for a list view.
I am able to set the pagination working perfectly for the list view but I wish to have a method being called when ever the user clicks on any of the page numbers in the data pager.
I want to perform some operation whenever the page number is called. I guess there is no onclick event, so is there any other way by which this is possible.
Thanks
you can set it as imagebutton or linkbutton.
I have piece of code.. you just need to implement it.
you can set link and click event.
foreach (DataPagerFieldItem dpfItem in dtpPaging.Controls)
{
foreach (Control cPagerControls in dpfItem.Controls)
{
if (cPagerControls is ImageButton)
{
ImageButton imgNavigation = cPagerControls as ImageButton;
imgNavigation.PostBackUrl = CommonLogic.GetFormattedURL(strPageUrl);
imgNavigation.Click += new ImageClickEventHandler(imgNavigation_Click);
}
if (cPagerControls is LinkButton)
{
LinkButton lnkNumbers = cPagerControls as LinkButton;
lnkNumbers.PostBackUrl = CommonLogic.GetFormattedURL(strPageUrl);
lnkNumbers.Click += new EventHandler(lnkNumbers_Click);
}
}
}
You can bind a handler to the OnPagePropertiesChanging Event of the List View. A PagePropertiesChangingEventArgs object is passed to the handler as argument which contains MaximumRows and StartRowIndex properties. You can use these to calculate the current page number. It is very easy and requires no code-behind event binding as the solution proposed by sikender.

ASP.NET: Postback processed without events being fired

I have a GridView with dynamically created image buttons that should fire command events when clicked. The event handling basically works, except for the very first time a button is clicked. Then, the postback is processed, but the event is not fired.
I have tried to debug this, and it seems to me, that the code executed before and after the first click is exactly the same as for any other clicks. (With the exception that in the first click, the event handler is not called.)
There is some peculiarity in that: The buttons which fire the event are created dynamically through databinding, i.e. databinding must be carried out twice in the page lifecycle: Once on load, in order to make the buttons exist (otherwise, events could not be handled at all), and once before rendering in order to display the new data after the events have been processed.
I have read these posts but they wouldn't match my situation:
ASP.NET LinkButton OnClick Event Is Not Working On Home Page,
LinkButton not firing on production server,
ASP.NET Click() event doesn't fire on second postback
To the details:
The GridView contains image buttons in each row. The images of the buttons are databound. The rows are generated by GridView.DataBind(). To achieve this, I have used the TemplateField with a custom ItemTemplate implementation. The ItemTemplate's InstantiateIn method creates the ImageButton and assigns it the according event handler. Further, the image's DataBinding event is assigned a handler that retrieves the appropriate image based on the respective row's data.
The GridView is placed on a UserControl. The UserControl defines the event handlers for the GridView's events. The code roughly looks as follows:
private DataTable dataTable = new DataTable();
protected SPGridView grid;
protected override void OnLoad(EventArgs e)
{
DoDataBind(); // Creates the grid. This is essential in order for postback events to work.
}
protected override void Render(HtmlTextWriter writer)
{
DoDataBind();
base.Render(writer); // Renews the grid according to the latest changes
}
void ReadButton_Command(object sender, CommandEventArgs e)
{
ImageButton button = (ImageButton)sender;
GridViewRow viewRow = (GridViewRow)button.NamingContainer;
int rowIndex = viewRow.RowIndex;
// rowIndex is used to identify the row in which the button was clicked,
// since the control.ID is equal for all rows.
// [... some code to process the event ...]
}
private void DoDataBind()
{
// [... Some code to fill the dataTable ...]
grid.AutoGenerateColumns = false;
grid.Columns.Clear();
TemplateField templateField = new TemplateField();
templateField.HeaderText = "";
templateField.ItemTemplate = new MyItemTemplate(new CommandEventHandler(ReadButton_Command));
grid.Columns.Add(templateField);
grid.DataSource = this.dataTable.DefaultView;
grid.DataBind();
}
private class MyItemTemplate : ITemplate
{
private CommandEventHandler commandEventHandler;
public MyItemTemplate(CommandEventHandler commandEventHandler)
{
this.commandEventHandler = commandEventHandler;
}
public void InstantiateIn(Control container)
{
ImageButton imageButton = new ImageButton();
imageButton.ID = "btnRead";
imageButton.Command += commandEventHandler;
imageButton.DataBinding += new EventHandler(imageButton_DataBinding);
container.Controls.Add(imageButton);
}
void imageButton_DataBinding(object sender, EventArgs e)
{
// Code to get image URL
}
}
Just to repeat: At each lifecycle, first the OnLoad is executed, which generates the Grid with the ImageButtons. Then, the events are processed. Since the buttons are there, the events usually work. Afterwards, Render is called, which generates the Grid from scratch based upon the new data. This always works, except for the very first time the user clicks on an image button, although I have asserted that the grid and image buttons are also generated when the page is sent to the user for the first time.
Hope that someone can help me understand this or tell me a better solution for my situation.
A couple problems here. Number one, there is no IsPostBack check, which means you're databinding on every load... this is bound to cause some problems, including events not firing. Second, you are calling DoDataBind() twice on every load because you're calling it in OnLoad and Render. Why?
Bind the data ONCE... and then again in reaction to events (if needed).
Other issue... don't bind events to ImageButton in the template fields. This is generally not going to work. Use the ItemCommand event and CommandName/CommandArgument values.
Finally... one last question for you... have you done a comparison (windiff or other tool) on the HTML rendered by the entire page on the first load, and then subsequent loads? Are they EXACTLY the same? Or is there a slight difference... in a control name or PostBack reference?
Well I think the event dispatching happens after page load. In this case, its going to try to run against the controls created by your first data-binding attempt. This controls will have different IDs than when they are recreated later. I'd guess ASP.NET is trying to map the incoming events to a control, not finding a control, and then thats it.
I recommend taking captures of what is in the actual post.
ASP.NET is pretty crummy when it comes to event binding and dynamically created controls. Have fun.
Since in my opinion this is a partial answer, I re-post it this way:
If I use normal Buttons instead of ImageButtons (in the exact same place, i.e. still using MyItemTemplate but instantiating Button instead of ImageButton in "InstantiateIn", it works fine.
If I assert that DoDataBind() is always executed twice before sending the content to the client, it works fine with ImageButtons.
Still puzzled, but whatever...

ASP.NET [Need an event after page load (After GridView renew data) ]

I renew parameters of my DataSource for GridView on Button and loads event Page_Load()
and After it (or with it) GridView renews itself.
I need to rename Header rows but there is no event after Page Load.
more information about details here :
[On Button Click] I change DataSource and Bind it (SqlDataSource1.DataBind(); ) Then sure Page gone to Refresh elements.
[On Page_Load] GridView is changing data, but if I can't change Headers there because it's looking like loads after this function :(
[one more Button] I can add new button with a function - rename headers and it works correct everytime
protected void Button2_Click(object sender, EventArgs e)
{
// Stack overflow
DataRow T;
if (go)
if (GridView2.HeaderRow.Cells.Count != 0)
for (int i = 0; i < SQF.SQF.Permission.Rows.Count; i++)
{
T = SQF.SQF.Permission.Rows[i];
GridView2.HeaderRow.Cells[i].Text = (string)T["Caption1"];
WebMsgBox.Show((string)T["Caption1"]);
}
}
Trouble : I no need one more button for it, I need to rename header rows after I click button to change Data but I have no idea where I can do it.
thank you.
Well you could use Gridview DataBound event, like that:
<asp:GridView runat="server" ID="SomeID" OnDataBound="GridVIew_OnDataBound" ... />
The DataBound event occurs right after the databinding process for that particular control has completed.
After Page_Load there is an event Page.PreRender.
Maybe it will suit you.
EDIT.
All events of your components, such as GridView, are fired between Page.Load and Page.PreRender. Consider using RowDataBound and RowUpdated events.

Resources