Dynamically created linkbuttons' common event not firing - c#

Whenever DropDownList SelectedIndexChanged, I am adding LinkButtons as ul-li list in codebehind. Each linkbuttons were assigned with IDs and a common Click event. Problem is code in Click event is not executed or maybe event is not triggered. My code below: [Edit] I tried like this as suggested in other posts (dynamically created list of link buttons, link buttons not posting back)
protected void ddl_SelectedIndexChanged(object sender, EventArgs e)
{
populate();
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
populate();
}
void populate()
{
HtmlGenericControl ulList = new HtmlGenericControl("ul");
panel.Controls.Add(ulList);
foreach (DataRow dr in drc)
{
HtmlGenericControl liList = new HtmlGenericControl("li");
ulList.Controls.Add(liList);
var lnk = new LinkButton();
lnk.ID = dr["col1"].ToString();
lnk.Text = dr["col1"].ToString();
lnk.Click += Clicked;
liList.Controls.Add(lnk);
}
}
private void Clicked(object sender, EventArgs e)
{
var btn = (LinkButton)sender;
label1.Text = btn.ID.ToString();
}
Im missing something. Any help please.

Here the issue is with the ViewState. When the selected index of the dropdownlist changes there is a postback which takes place and the previous state is lost, so at this point you have to maintain the state of the controls.
Now in your code actually the state of the control is lost and so the click event does not fire. So the solution is to maintain the state of the controls.
The Below is a working example, you can just paste it and try.
This is my page load.
protected void Page_Load(object sender, EventArgs e)
{
for (var i = 0; i < LinkButtonNumber; i++)
AddLinkButton(i);
}
Similarly you have to maintain the state of the previously added control like this.
private int LinkButtonNumber
{
get
{
var number = ViewState["linkButtonNumber"];
return (number == null) ? 0 : (int)number;
}
set
{
ViewState["linkButtonNumber"] = value;
}
}
The below is my SelectedIndexChanged Event for the DropDownList
protected void Example_SelectedIndexChanged(object sender, EventArgs e)
{
AddLinkButton(LinkButtonNumber);
LinkButtonNumber++;
}
I have a function which dynamically creates the controls, which is called on the page load and on SelectedIndexChanged.
private void AddLinkButton(int index)
{
LinkButton linkbutton = new LinkButton { ID = string.Concat("txtDomain", index) };
linkbutton.ClientIDMode = ClientIDMode.Static;
linkbutton.Text = "Link Button ";
linkbutton.Click += linkbutton_Click;
PanelDomain.Controls.Add(linkbutton);
PanelDomain.Controls.Add(new LiteralControl("<br />"));
}
And this is the Click event for the LinkButton
void linkbutton_Click(object sender, EventArgs e)
{
//You logic here
}

I solved it using brute code lol.
Since controls' event were not bound on postback then we recreate them on postback. So in my Page_Load I called the module that re-creates the controls, thus binding them to corresponding event. This works, but...
Re-creating these controls create duplicates (Multiple Controls with same ID were found) and you will get into trouble in instances of finding a control by ID like using panel.FindControl.
To remedy this scenario, I put a check if same control ID already existed before recreating them, and voila! It works.
protected void Page_Load(object sender, EventArgs e)
{
populate();
}
void populate()
{
HtmlGenericControl ulList = new HtmlGenericControl("ul");
panel.Controls.Add(ulList);
foreach (DataRow dr in drc)
{
HtmlGenericControl liList = new HtmlGenericControl("li");
ulList.Controls.Add(liList);
if (liList.FindControl(dr["col1"].ToString()) == null)
{
var lnk = new LinkButton();
lnk.ID = dr["col1"].ToString();
lnk.Text = dr["col1"].ToString();
lnk.Click += Clicked;
liList.Controls.Add(lnk);
}
}
}

Related

Setting an event handler on a linkbutton inside a class Appointment Template won't fire

I have a telerik RadScheduler control which I am creating a custom appointment template for. The template binds succesfully, however sat inside my template is a linkbutton which I want to bind an event to. I can see that the event binds, however it does not call the code and hit the response.redirect, instead the page refreshes and the appointment templates dissapear. How do I get the event to handle correctly on the button click? The apptemplate is being appended on the page load.
public class AppTemplate : ITemplate
{
public void InstantiateIn(Control container)
{
SchedulerAppointmentContainer aptCont = (SchedulerAppointmentContainer)container;
Appointment app = aptCont.Appointment;
LinkButton lbs = new LinkButton();
lbs.ID = "btnConductAppointment";
lbs.Text = "<div style=\"font-weight:bold;\">" + app.Attributes["ApptClientID"] + "</div><div>" + app.Attributes["Title"] + " " + app.Attributes["Surname"] + "</div>";
//nlbs.Click += btnConductAppointment_Click;
lbs.DataBinding += new EventHandler(label1_DataBinding);
lbs.CausesValidation = false;
container.Controls.Add(lbs);
}
private void label1_DataBinding(object sender, EventArgs e)
{
LinkButton target = (LinkButton)sender;
target.Click += new EventHandler(btnConductAppointment_Click);
}
protected void btnConductAppointment_Click(object sender, EventArgs e)
{
HttpContext.Current.Response.Redirect(PageDirectory.Default, true);
}
}
Putting the bind in on the PageInit Means the event always exists.
protected override void OnInit(EventArgs e)
{
RadScheduler1.AppointmentTemplate = new AppTemplate();
}

assign event to ImageButton.Click from code behind

I want to assign events to each ImageButton from code behind, but i can not find out how to write a proper one.
foreach (string one in urls)
{
ImageButton temIBTN = new ImageButton();
temIBTN.Attributes.Add("Width","265px");
temIBTN.Attributes.Add("Width", "144px");
temIBTN.ImageUrl = one;
temIBTN.Click +=
new EventHandler(setBigPic(sender, e, one));//<---don't know how...
}
protected void setBigPic(object sender, ImageClickEventArgs e,string url)
{
img_Big.ImageUrl = url;
}
Your method signature for the event handler was wrong, and you need to get the ImageUrl from the button that's firing the event. This should do it:
foreach (string one in urls)
{
ImageButton temIBTN = new ImageButton();
temIBTN.Attributes.Add("Width","265px");
temIBTN.Attributes.Add("Width", "144px");
temIBTN.ImageUrl = one;
temIBTN.Click += setBigPic;
}
protected void setBigPic(object sender, ImageClickEventArgs e)
{
img_Big.ImageUrl = ((ImageButton)sender).ImageUrl;
}

add a button click event dynamically in asp.net 4.5 c#

I have some questions to this post [1]: How can i create dynamic button click event on dynamic button?
The solution is not working for me, I created dynamically an Button, which is inside in an asp:table controller.
I have try to save my dynamic elements in an Session, and allocate the Session value to the object in the Page_Load, but this is not working.
Some ideas
edit:
...
Button button = new Button();
button.ID = "BtnTag";
button.Text = "Tag generieren";
button.Click += button_TagGenerieren;
tabellenZelle.Controls.Add(button);
Session["table"] = table;
}
public void button_TagGenerieren(object sender, EventArgs e)
{
TableRowCollection tabellenZeilen = qvTabelle.Rows;
for (int i = 0; i < tabellenZeilen.Count; i++)
{
...
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
if (Session["table"] != null)
{
table = (Table) Session["table"];
Session["table"] = null;
}
}
}
It is not a good practice to store every control into Session state.
Only problem I found is you need to reload the controls with same Id, when the page is posted back to server. Otherwise, those controls will be null.
<asp:PlaceHolder runat="server" ID="PlaceHolder1" />
<asp:Label runat="server" ID="Label1"/>
protected void Page_Load(object sender, EventArgs e)
{
LoadControls();
}
private void LoadControls()
{
var button = new Button {ID = "BtnTag", Text = "Tag generieren"};
button.Click += button_Click;
PlaceHolder1.Controls.Add(button);
}
private void button_Click(object sender, EventArgs e)
{
Label1.Text = "BtnTag button is clicked";
}
Note: If you do not know the button's id (which is generated dynamically at run time), you want to save those ids in ViewState like this - https://stackoverflow.com/a/14449305/296861
The problem lies in the moment at which te button and it's event are created in the pagelifecycle. Try the page_init event for this.
Create Button in page load
Button btn = new Button();
btn.Text = "Dynamic";
btn.Click += new EventHandler(btnClick);
PlaceHolder1.Controls.Add(btn)
Button Click Event
protected void btnClick(object sender, EventArgs e)
{
// Coding to click event
}

Linkbutton click event does not work inside gridview

I have a webpage where I have a gridview. I have populated the gridview on page load event.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
loadGridView();
}
}
This is the load gridview method.
private void loadGridView()
{
dataTable dt = getData(); // this function populates the data table fine.
gridView1.dataSource = dt;
gridview1.dataBind();
}
Now I have added linkButtons in one of the gridview columns in the RowDataBound event of the grid view.
protected void gvTicketStatus_RowDataBound(object sender, GridViewRowEventArgs e)
{
LinkButton lb = new LinkButton();
lb.Text = str1; // some text I am setting here
lb.ID = str2; // some text I am setting here
lb.Click += new EventHandler(lbStatus_click);
e.Row.Cells[3].Controls.Add(lb);
}
Finally This is the event Handler code for the link button click event.
private void lbStatus_click(object sender, EventArgs e)
{
string str = ((Control)sender).ID;
// next do something with this string
}
The problem is, the LinkButtons appear in the data grid fine, but the click event does not get execute. the control never reaches the event handler code. when I click the link button, the page simply gets refreshed. What could be the problem?
I have tried calling the loadGridView() method from outside the (!isPostBack) scope, but it did not help!
Try to work with the "Command" property instead of Click event
LinkButton lnkStatus = new LinkButton();
lnkStatus.ID = string.Format("lnkStatus_{0}", value);
lnkStatus.Text = "some text here";
lnkStatus.CommandArgument = "value";
lnkStatus.CommandName = "COMMANDNAME";
lnkStatus.Command += new CommandEventHandler(lnkStatus_Command);
Otherwise, if my proposal doesn't satisfy you, you have to remove the !Postback on Page_Load event.
you have to use OnRowCommand event of the GridView.
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName.Equals("LinkButton1")) //call the CommandArgument name here.
{
//code
}
}

how to create event handler for dynamic drop down list in c#

I have created a dynamic grid view using Itemplate .now i have also created a dynamic drop down list in the grid . how to create a event handler for on selectedindexchange .
i created a slectedindexchange event but it didnt work .the control never passes to the event ?
what to do create a event handler
public class DynamicGridViewTextTemplate : ITemplate
{
string _ColName;
DataControlRowType _rowType;
int _Count;
details Details1 = new details();
public DynamicGridViewTextTemplate(string ColName, DataControlRowType RowType)
{
_ColName = ColName;
_rowType = RowType;
}
public DynamicGridViewTextTemplate(DataControlRowType RowType, int ArticleCount)
{
_rowType = RowType;
_Count = ArticleCount;
}
public void InstantiateIn(System.Web.UI.Control container)
{
switch (_rowType)
{
case DataControlRowType.Header:
Literal lc = new Literal();
lc.Text = "<b>" + _ColName + "</b>";
DropDownList ddl = new DropDownList();
ddl.AutoPostBack = true;
ddl.SelectedIndexChanged += new EventHandler(this.ddl_SelIndexChanged);
container.Controls.Add(lc);
container.Controls.Add(ddl);
break;
case DataControlRowType.DataRow:
//Label lbl = new Label();
//lbl.DataBinding += new EventHandler(this.lbl_DataBind);
LinkButton lb = new LinkButton();
lb.DataBinding += new EventHandler(this.lbl_DataBind);
lb.OnClientClick +=new EventHandler(this.lb_Click);
//lbl.Controls.Add(lb);
container.Controls.Add(lb);
break;
case DataControlRowType.Footer:
Literal flc = new Literal();
flc.Text = "<b>Total No of Articles:" + _Count + "</b>";
container.Controls.Add(flc);
break;
default:
break;
}
}
private void lb_Click(Object sender, EventArgs e)
{
details1.lbl_Click(sender, e);
}
private void lbl_DataBind(Object sender, EventArgs e)
{
//Label lbl = (Label)sender;
LinkButton lbl = (LinkButton)sender;
GridViewRow row = (GridViewRow)lbl.NamingContainer;
lbl.Text =DataBinder.Eval(row.DataItem, _ColName).ToString();
}
public void ddl_SelIndexChanged(Object sender, EventArgs e)
{
Details1.ddlFilter_SelectedIndexChanged(sender,e);
}
}
you can declare you selectedindexchanged event like this:
ddlFilter.SelectedIndexChanged += new EventHandler(ddl2_SelectedIndexChanged);
ddlFilter.AutoPostBack = true;
void ddlFilter_SelectedIndexChanged(object sender, EventArgs e)
{
//your code
}
The reason your event wasn't called is the AutoPostBack=true field. If you don't set it to true your selectedIndexChanged event will never be called.
Whenever I create a new Control in an ASP web page I follow this boiler plate (note that I added some example controls so it's not a "clean" boiler plate):
namespace Components {
[ToolboxData("<{0}:MyControl runat=server></{0}:MyControl>")]
public class MyControl : WebControl, INamingContainer {
// todo: add controls that are created dynamically
private GridView gridView;
public MyControl () {
Initialize();
}
[Browsable(false)]
public override ControlCollection Controls {
get { EnsureChildControls(); return base.Controls; }
}
protected override void OnLoad(EventArgs e) {
// todo: attach event listeners for instance
base.OnLoad(e);
}
protected override void CreateChildControls() {
Initialize();
}
protected override void Render(HtmlTextWriter writer) {
if (DesignMode) {
// If special design mode rendering
return;
}
base.Render(writer);
}
/// This is where the controls are created
private void Initialize() {
base.Controls.Clear();
// todo: Create all controls to add, even those "added later"
// if something is generated but should not be shown,
// set its Visible to false until its state is changed
Label exampleLabel = new Label();
exampleLabel.Visible = false; // like so
if (gridView == null) { gridView = new GridView(); }
base.Controls.Add(exampleLabel);
base.Controls.Add(gridView);
}
}
}
Now, if you create your dynamic drop down in Initialize and add it to your Controls collection every time but only set its Visibility to true when you want it to show, your event should be triggered, since the id's of your controls should be the same between postbacks.
Dynamic control's event to occure, it is required that it should be created and event assigned in page_load event or during the page_load event occures. Control's event will fire after Page_Load event completes. If control is not recreated in page_load event, event will not bind to the control and will not fire.
I had the same problem and I was creating the dynamic ddl inside (!Page.IsPostBack). When i moved the creation outside the (!Page.IsPostBack) it worked fine.
You must create your elements outside the (!Page.IsPostBack) like MUG4N said and it should work fine.
Thats how I did it with a Dropdownlist generated out of a ComboBox
code :
setConnectionToolStripMenuItem.DropDownItems.AddRange(toolStripComboBoxConnections.Items.Cast<string>().Select(text => new ToolStripMenuItem(text, null, new EventHandler(DropDown_Click_Event))).ToArray());

Categories