ImageButton inside cell table doesn't work - asp.net

If I create ImageButton dynamically and add this into table cell
TableRow tr = new TableRow();
TableCell tc = new TableCell();
ImageButton imagebutton= new ImageButton();
imagebutton.imageurl=imageurl;
imagebutton.click+= new System.Web.UI.ImageClickEventHandler(click);
tc.Controls.Add(imagebutton);
tr.Controls.Add(tc);
Table1.Rows.Add(tr);
The click event doesnt' work.
However, if I use Panel instead of table the imagebutton works. Morevoer If I add imagebutton to the page directly it also works.
But I need store imagebutton in a table cell.
What is a problem?
How to make working imagebutton inside asp table?
The method click is:
protected void click(object sender, EventArgs e)
{
Response.Write("<script type='text/javascript'>alert('OK!');</script>");
}

What is a problem?
This seems to be a classic asp.net page life-cycle problem. It's cause is probably that, a the time the click should be handled, your button, as well as your table, do not exist because you create it later in the page life cycle (say in pre_render), or you only create when not on postback, or in another control event handler.
How to make working imagebutton inside asp table?
Your table and button creation , as well as click handler binding should be located in
page_load (even better, in Init, when using view_state for dynamic controls)
The code should run whether on postback or not.
Hope this will help

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);

ASP.NET Boundfield changes when I update another gridview

I have a boundfield in a gridview that programatically receives a hyperlink for the content in it. It gets a new dataset after a drop down list index change. One of the columns of the dataset will apply links to fields with data and skip those without, you can see my logic for applying links below:
if (e.Row.DataItem != null && int.TryParse(e.Row.Cells[4].Text, out incidents))
{
HyperLink incidentsLink = new HyperLink();
incidentsLink.ForeColor = System.Drawing.Color.Blue;
incidentsLink.NavigateUrl = "~/somesite.aspx?no=" + stnNum + "&dt=" + date;
incidentsLink.Text = e.Row.Cells[4].Text;
e.Row.Cells[4].Controls.Add(incidentsLink);
}
This is applied OnRowDataBound for the gridview. Then I have another gridview that is wired to another drop down list. When either drop down list changes index it grabs a new dataset for the related gridview and fires a ajax update using an update panel.
What happens is when the second gridview updates it erases the links in the first gridview. It doesn't erase the text, that stays, but the text is no longer anchored to a link. All links made this way and put into gridviews lose their link properties, however fields created using asp:HyperLinkField are left unchanged. The problem is that stnNum and date are not a part of the dataset that is returned for the first gridview, so I have to add them as a link after the gridview is already built.
The only solution I can think of is to refire the function that adds links to the gridview each time the second gridview updates. Any other solutions would be helpful, or an explanation as to why my link is being erased would be great.
Try binding the GridView/DropDowns only if there is not any POSTBACK. I believe POST Back event is letting your gridview & Controls to loose their data somehow.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Bind your Grids & Dropdowns here on page load
}
}

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...

CheckedChanged event for checkbox not firing for dynamic checkboxes

I seem to be having an issue getting the event handler for a group of dynamic checkboxes. The code is posted here. I thought this would be pretty straight forward, the checkboxes do not appear in a repeater, datagrid, etc. They appear in a table which is located inside a div which positioned in the center of the screen. Any help would greatly appreciated.
foreach (SelectAssignedRolesByUserResult role in assignedRoles)
{
CheckBox cb = new CheckBox();
cb.ID = string.Format("CheckBox_{0}_{1}", role.role_nm, role.role_id);
cb.Text = role.role_nm;
cb.Attributes.Add("role_id", role.role_id.ToString());
cb.Attributes.Add("assigned_role_id", role.assigned_role_id.ToString());
cb.Checked = (role.assigned_role_id > 0);
cb.CheckedChanged += new EventHandler(cb_CheckedChanged);
TableCell cell = new TableCell();
TableRow row = new TableRow();
cell.Controls.Add(cb);
row.Cells.Add(cell);
TableAssignedRoles.Rows.Add(row);
}
You don't mention where the code that dynamically adds the checkboxes is called. I'm guessing you put this in the Page_Load event handler, or in a sub that is called from within Page_Load.
If so, move it from Page_Load to Page_Init.
This is a very non-technical explanation of the reasoning for this:
This is because whether or not the controls are selected happens when the page parses the Viewstate. In the page lifecycle, the Page_Init loads the initial controls, then the viewstate is applied, and then the Page_Load fires.
Added
And don't forget to add
cb.AutoPostBack = true;
Can we see some more code? At what point in the lifecycle are you calling the above code?
If you're not recreating the checkboxes in exactly the same way on every postback, such that each Checkbox is assigned the same ID and can load ViewState properly, you'll lose your event handlers.

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

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";

Resources