Adding controls to a table control dynamically - c#

I have one table control "table1"
And added controls to it in click event of one button as :
protected void Button2_Click(object sender, EventArgs e)
{
TableRow row;
TableCell cell;
for (int i = 0; i < 3; ++i)
{
TextBox txt = new TextBox();
txt.Text = i.ToString();
row = new TableRow();
cell = new TableCell();
cell.Controls.Add(txt);
row.Controls.Add(cell);
Table1.Controls.Add(row);
}
}
but i cant retrieve this controls in click event of another button. i think it is because of postback.
How can i prevent it?

When adding controls dynamically, if you want to access them on postback, you need to re-create them every time the page is loaded.
Adding them in the click handler of one button and expecting them to be there for the click handler of another button will not work, as they have not been re-created on the second postback.
You need to understand the asp.net page life cycle and change the logic of your page to fit in with it.

Related

Dynamic Button not triggered in ASP.Net from static class

I am trying to make a dynamic table which has a couple of rows and the last row is a plus button, which will add a new row. (I will only describe the important information, to keep it simple.)
I thought of this way to accomplish it:
// .aspx code
<li><asp:LinkButton ID="LM_Show" runat="server" Text="Show list" OnClick="Action"/></li>
<asp:PlaceHolder ID="infoTable" runat="server"></asp:PlaceHolder>
//CreateTable function
public void Clicked(object sender, EventArgs e){
table();
}
public void table() {
//Do stuff...
//Screen variable is keeping track of which screen should be shown in .aspx
infoTable.Controls.Add(CreateView.createTable<Employee>(screen, this.Context, table));
}
//Create the actual table
public static Table createTable<T>(Screen screen, HttpContext context, Action method) where T : new() {
//New table and make it stretch
Table tb = new Table();
tb.Width = Unit.Percentage(100);
tb.Height = Unit.Percentage(100);
//Gather list from session
List<T> items = (List<T>)context.Session["list"];
//Create table content based on the list
for (int i = 1; i <= items.Count(); i++) {
TableRow tr = new TableRow();
//Foreach property create cells with content according to the property
//Add these cells to the row
tb.Rows.Add(tr);
}
//Create 1 final row which has a button to be able to add 1 row
TableRow tr2 = new TableRow();
TableCell tc = new TableCell();
tr.Cells.Add(tc);
//Create the Button
Button button = new Button();
button.Text = "+";
//!!This is not getting triggered!!//
button.Click += (s, e) => {
List<T> tempItems = (List<T>)context.Session["list"];
tempItems.Add(new T());
context.Session["list"] = tempItems;
//When a button is pressed, it gives a postback.
//The table has to be rebuild over again with the newly added item
method();
};
//!!This is not getting triggered!!//
//Add the button
tr2.Cells[0].Controls.Add(button);
tb.Rows.Add(tr2);
return tb;
}
Any comments about the code or how to accomplish it even better are also very welcome.
This could be achieved more easily if you used jQuery AJAX and communicate with a web service/method to get the data. However, it can be achieved in C# as well. Assuming that the given below part of the code is not working,
//Add the button
tr2.Cells[0].Controls.Add(button);
tb.Rows.Add(tr2);
You can try adding button to tc first, and then add tc to the row tr
tc.Controls.Add(button);
tr2.Cells.Add(tc);
tb.Rows.Add(tr2);
Good Luck!

Dynamically created image button click event is not fired

On dynamically created table based on some condition i've added imagebutton dynamically. parallelly i want to add event for this image button click but the click event is not getting fired. here is my code snippet.
private void createTable()
{
TableRow tableRow = new TableRow();
TableCell ImageCell = new TableCell();
ImageButton imgBtndeleteAttr = new ImageButton();
imgBtndeleteAttr.ID = "imgbtn_" + i.ToString() + j.ToString();
imgBtndeleteAttr.CssClass = "deleteDynamic";
imgBtndeleteAttr.OnClientClick = "javascript:return confirm('Do you want to delete this Attribute?');";
imgBtndeleteAttr.Click += new System.Web.UI.ImageClickEventHandler(imgBtndeleteAttr_Click);
ImageCell.Controls.Add(imgBtndeleteAttr);
tableRow.Cells.Add(ImageCell);
}
and here is the event
protected void imgBtndeleteAttr_Click(object sender, ImageClickEventArgs e)
{
ClientScript.RegisterClientScriptBlock(this.GetType(), "lnk",
"<script type = 'text/javascript'>alert('Image button Clicked');</script>");
}
Its a bad idea to use dynamic controls in asp. The controls have to be recreated on postback. So if you create a button dynamically and click it, postback happens and event is triggered but due to postback the button which triggered the event is destroyed and the raised event is discarded.

Adding Triggers dynamically on UpdatePanel for dynamially added controls

I am Adding array Buttons to a simple panel dynamically which is located in an Update Panel, now I want to Add triggers for UpdatePanel on click event of these buttons. My codes is as below:
protected void AddButtons()
{
Button[] btn = new Button[a];
for (int q = 0; q < a; q++)
{
btn[q] = new Button();
buttonsPanel.Controls.Add(btn[q]);
btn[q].ID = "QID" + q;
btn[q].Click += new EventHandler(_Default_Click);
btn[q].Attributes.Add("OnClick", "Click(this)");
AsyncPostBackTrigger trigger = new AsyncPostBackTrigger();
trigger.ControlID = btn[q].ID;
trigger.EventName = "Click";
UpdatePanel2.Triggers.Add(trigger);
}
}
Now click event is not fired when i click on any of these bottons and buttons are getting removed.
Please note that these buttons are not available on Page_Init() method.
You need to assign UniqueID instead of ID to AsyncPostBackTrigger.ControlID property. Try to use the following code:
AsyncPostBackTrigger trigger = new AsyncPostBackTrigger();
trigger.ControlID = btn[q].UniqueID;
trigger.EventName = "Click";
UpdatePanel2.Triggers.Add(trigger);
I came across this post when I was attempting to dynamically add triggers to an update panel which contained a gridview. I have buttons in the gridview and defining the trigger in the page doesn't work as a unique ID for each button is generated when each row is created.
Generating the trigger like such;
AsyncPostBackTrigger trigger = new AsyncPostBackTrigger();
trigger.ControlID = btn[q].UniqueID;
trigger.EventName = "Click";
UpdatePanel2.Triggers.Add(trigger);
did not work for me. The control could not be found, however when using the RegisterPostbackControl or the RegisterAysncPostbackControl commands it worked.
The end example is as follows;
protected void BankAccountDocumentGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
LinkButton linkButton = (LinkButton)e.Row.Cells[3].FindControl("DocumentsDownloadButton");
ScriptManager.GetCurrent(Page).RegisterPostBackControl(linkButton);
}
}
I figured that the original poster or others who come across this post may benefit from my findings.

How to add buttons to datagridview cells not entire column

How do you add a button to cells in a row and not the entire column in a datagridview?
I think Adrian's answer was close. Try something like this.
if ((string)table.Rows[0].Cells[0].Value == "I should be a button") {
// you can add formatting or values to the button before assigning it here
table.Rows[0].cells[0] = new DataGridViewButtonCell();
}
I think the best answer if found here:
Hide gridview button. All you need to do is to add a DataGridViewButtonCell where you want buttons, and DataGridViewTextBoxCell where you do not. The column has to be DataGridViewButton type.
See this similar post in SO, probably helps
adding control to gridview
In case Win Form, Check this MSDN post
Column Types in the Windows Forms DataGridView Control
OR this code project post ... though it gives example of adding a image button
DataGridView Image Button Cell
#tmax In that case you can probably put your button creation code in GridView_RowCreated event like below
void GridView_RowCreated(Object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.Header)
{
//Button creation code here
}
}
private void dataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
Button btn = new Button();
//btn attributes
dataGridView1.Rows[0].Cells[3].Value = new Button();
}
try something like this.
What I endded up doing was stacking a DataGridView on top of another one. I turned off the border, gridlines, and scrollbars. Then create dynamic button columns to match the main datagridview with only one row of buttons. Then I used the ColumnWidthChanged event handler to resize both the DataGridViews together. Anyway's this was my workaround for now.
DataGridViewButtonColumn dataGridViewButtonColumn = new DataGridViewButtonColumn();
dataGridViewButtonColumn.Name = "Select";
dataGridViewButtonColumn.HeaderText = "Select";
dataGridViewButtonColumn.ReadOnly = false;
dataGridView1.Columns.Add(dataGridViewButtonColumn);
After assigning data source to gridviewCTRL. you can add new column with button with below code.
DataGridViewButtonColumn startbtn = new DataGridViewButtonColumn();
startbtn.Name = "Action";
startbtn.Text = "Start";
startbtn.UseColumnTextForButtonValue=true;
int columnIndex = 6;
gridviewCTRL.Columns.Insert(columnIndex, startbtn);
This will add the button to each and every row at define column index.
if you want to render condition the AccessibleObject, then you can do something similar to below.
foreach (DataGridViewRow rowdata in gridviewCTRL.Rows)
{
// this is just an example in my case i am checking a previous column value
if (rowdata.Cells[5].Value=="XYZ")
{
rowdata.Cells[6] = new DataGridViewTextBoxCell();
}
}
This way you can dynamically render/ showing the control in the GridView in Winforms c#.
The above code simple update the cell with new cell. We can't remove button from the cell nor remove whole, so instead we can initial a new cell that will override the button visibility.
I am not sure if this will help but you can also consider using TableLayoutPanel.
Refer: Winforms TableLayoutPanel adding rows programmatically

asp.net - Button event does not fire up

I have a search button on my page that runs a query on a DB, pulls out and displays some entries in a table, and for each entry I create a button. It looks something like this:
List<Friend> friends = SearchFriend(searchStr);
foreach (Friend f in friends)
{
TableCell addCell = new TableCell(), nameCell = new TableCell();
addCell.Text = "";
if (!f.IsMyFriend)
{
LinkButton addFriendBtn = new LinkButton();
addFriendBtn.Text = "Add as Friend";
addFriendBtn.Click += new EventHandler(addFriendBtn_Click);
addFriendBtn.ID = "add_" + f.ID.ToString();
addCell.Controls.Add(addFriendBtn);
}
nameCell.Text = f.Name;
TableRow row = new TableRow();
row.Cells.Add(addCell);
row.Cells.Add(nameCell);
SearchFriendTable.Rows.Add(row);
}
Problem is that the LinkButton event does not fire when it is pressed (changing LinkButton to a simple Button does not fix this either).
This is the html that I get in this portion:
<td><a id="ctl00_contentPH_add_2" href="javascript:__doPostBack('ctl00$contentPH$add_2','')">Add as Friend</a></td>
Also - when I put a breakpoint on Page_Load I do see the __EVENTTARGET with this control's id in it - however the event never starts running.
Any clues?
Thanks.
Adding to Himadri's answer:
Dynamically added controls need to be rewired in page init. Then the event will fire. I had a very similar issue Dynamically loaded Controls in a wizard
Where and when did you created that button?
If you dynamically create Buttons and want to listen to a event you have to create that button in the PageInit event. Always! So do not use if(!IsPostback)
Try with this.
<td><a id="ctl00_contentPH_add_2" href="javascript:__doPostBack('<%=ct100_contentPH_add_2.ClientId %>','')">Add as Friend</a></td>
Add event handler for the link buttons and handle those events.
if (!f.IsMyFriend)
{
LinkButton addFriendBtn = new LinkButton();
addFriendBtn.Text = "Add as Friend";
addFriendBtn.Click += new EventHandler(addFriendBtn_Click);
addFriendBtn.ID = "add_" + f.ID.ToString();
addFriendBtn.Click += new EventHandler(addFriendBtn_Click);
addCell.Controls.Add(addFriendBtn);
}
the event:
protected void addFriendBtn_Click(object sender, EventArgs e)
{
LinkButton lnk = (LinkButton)sender;
// do your coding
}

Categories