Dynamic Control’s Event Handler’s Working - c#

I have following code that adds dynamic LinkButton on the click event of a normal button. The LinkButtons need a EventHandler “LinkButton_Click“. Since the event handler need to be registered while Page_Load/Page_Init itself, I am first adding all the possible links within Page_Load (in postback scenario). (There are totally fours linkbuttons; only two will be displayed in the screen based on business scenario)
The code is working fine and the event handlers are getting invoked on click event.
Note: The business scenario is – if the current time’s second portion is less than 30, the first two LinkButtons need to be displayed; if greater than 30 the last two LinkButtons need to be displayed.
Note: The controls are cleared and added again inside PopulateLinksBasedOnCriteria() method
QUESTIONS
In the PopulateLinksBasedOnCriteria() method, I am newly creating the link button instances. Still the event handler is firing. This is working because the ID that got added in the Page_Load is same. Is there any MSDN reference that substantiate this behavior? (I.e. the event handler will be based on the IDs registered while Page_Load/Page_Init. This will work even if the controls are cleared and added again)
There is duplicate code in creating LinkButtons – one inside Page_Load and other inside PopulateLinksBasedOnCriteria() method. Is there a better way to achieve this business task without duplicate code?
MarkUp
<form id="form1" runat="server">
<div>
<asp:Button ID="btnAdd" runat="server" Text="Add" OnClick="btnAdd_Click" />
<br />
<asp:PlaceHolder ID="plhDynamicLinks" runat="server"></asp:PlaceHolder>
</div>
</form>
CODE BEHIND
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
LinkButton lnk1 = new LinkButton();
lnk1.ID = "D1";
lnk1.Text = "A";
//Event handler must be registered in the Page_Load/Page_Init
lnk1.Click += new EventHandler(LinkButton_Click);
plhDynamicLinks.Controls.Add(lnk1);
LinkButton lnk2 = new LinkButton();
lnk2.ID = "D2";
lnk2.Text = "B";
lnk2.Click += new EventHandler(LinkButton_Click);
plhDynamicLinks.Controls.Add(lnk2);
LinkButton lnk3 = new LinkButton();
lnk3.ID = "D3";
lnk3.Text = "C";
lnk3.Click += new EventHandler(LinkButton_Click);
plhDynamicLinks.Controls.Add(lnk3);
LinkButton lnk4 = new LinkButton();
lnk4.ID = "D4";
lnk4.Text = "D";
lnk4.Click += new EventHandler(LinkButton_Click);
plhDynamicLinks.Controls.Add(lnk4);
}
}
protected void LinkButton_Click(object sender, EventArgs e)
{
PopulateLinksBasedOnCriteria();
LinkButton clickedControl = (LinkButton)sender;
Response.Write(DateTime.Now.ToString()+"___"+ clickedControl.ID + " Link Button Clicked" );
}
protected void btnAdd_Click(object sender, EventArgs e)
{
PopulateLinksBasedOnCriteria();
}
private void PopulateLinksBasedOnCriteria()
{
plhDynamicLinks.Controls.Clear();
if (DateTime.Now.Second < 30)
{
LinkButton linkButton1 = new LinkButton();
linkButton1.ID = "D1";
linkButton1.Text = "1";
plhDynamicLinks.Controls.Add(linkButton1);
LinkButton linkButton2 = new LinkButton();
linkButton2.ID = "D2";
linkButton2.Text = "2";
plhDynamicLinks.Controls.Add(linkButton2);
}
else
{
LinkButton linkButton3 = new LinkButton();
linkButton3.ID = "D3";
linkButton3.Text = "3";
plhDynamicLinks.Controls.Add(linkButton3);
LinkButton linkButton4 = new LinkButton();
linkButton4.ID = "D4";
linkButton4.Text = "4";
plhDynamicLinks.Controls.Add(linkButton4);
}
}

I would suggest detecting what causes the PostBack in Page_Load Event On postback, how can I check which control cause postback in Page_Init event and then
if (Page.IsPostBack && *PostBackControl.Name=="btnAdd"*)
{
if (DateTime.Now.Second < 30)
{
LinkButton lnk1 = new LinkButton();
lnk1.ID = "D1";
lnk1.Text = "A";
//Event handler must be registered in the Page_Load/Page_Init
lnk1.Click += new EventHandler(LinkButton_Click);
plhDynamicLinks.Controls.Add(lnk1);
LinkButton lnk2 = new LinkButton();
lnk2.ID = "D2";
lnk2.Text = "B";
lnk2.Click += new EventHandler(LinkButton_Click);
plhDynamicLinks.Controls.Add(lnk2);
} else
{
LinkButton lnk3 = new LinkButton();
lnk3.ID = "D3";
lnk3.Text = "C";
lnk3.Click += new EventHandler(LinkButton_Click);
plhDynamicLinks.Controls.Add(lnk3);
LinkButton lnk4 = new LinkButton();
lnk4.ID = "D4";
lnk4.Text = "D";
lnk4.Click += new EventHandler(LinkButton_Click);
plhDynamicLinks.Controls.Add(lnk4);
}
}
}

Related

CheckBox CheckedChanged event added from code behind

I have a couple of checkboxes that I add from my code behind, but I can't get the CheckedChanged event to fire.
This code is being called on page load:
CheckBox cb = new CheckBox();
cb.AutoPostBack = true;
cb.CheckedChanged += cb_CheckedChanged;
cb.ToolTip = dr["Id"].ToString();
cb.ID = Guid.NewGuid().ToString();
Label lbl = new Label();
lbl.Text = dr["Id"].ToString();
lbl.AssociatedControlID = cb.ID;
dvCheckboxes.Controls.Add(cb);
dvCheckboxes.Controls.Add(lbl);
dvCheckboxes.Controls.Add(new LiteralControl("<br />"));
And the event:
void cb_CheckedChanged(object sender, EventArgs e)
{
System.Diagnostics.Debug.Write(((CheckBox)sender).ToolTip);
}
I've put a breakpoint in the CheckedChanged event, but it's never reached.
What I've tried:
putting the code in if(!IsPostBack), but no difference.
cb.CheckedChanged += new EventHandler(cb_CheckedChanged);
cb.CheckedChanged += new EventHandler(this.cb_CheckedChanged);
cb.ViewStateMode = System.Web.UI.ViewStateMode.Enabled;
tried putting the code in Page_Init instead of Page_Load
#johan, Try this. Create the checkboxes in PageInit instead of Pageload. Also provide an appropriate id for the Checkbox.
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Page_init(object sender, EventArgs e)
{
CheckBox cb = new CheckBox();
cb.AutoPostBack = true;
cb.CheckedChanged +=cb_CheckedChanged;
cb.CausesValidation = false;
cb.ToolTip = "Hello";
cb.ID = "chk_test";
Label lbl = new Label();
lbl.Text = "test";
lbl.AssociatedControlID = cb.ID;
dvCheckboxes.Controls.Add(cb);
dvCheckboxes.Controls.Add(lbl);
dvCheckboxes.Controls.Add(new LiteralControl("<br />"));
}
protected void cb_CheckedChanged(object sender, EventArgs e)
{
System.Diagnostics.Debug.Write(((CheckBox)sender).ToolTip);
}
Add event in your site code - not code behind:
<asp:CheckBox ID="cb" Runat="server" CheckedChanged="cb_CheckedChanged" />
Hope this helps.

dynamic linkbutton not calling command when clicked

New to dynamic controls, but until now I have been creating them successfully in a
template field in my gridview, recently switched from a hyperlink to a link button
and had to make some changes but still not working
In my page I have the following code (abridged to salient parts)
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
...
...
TemplateField tf = new TemplateField();
tf.HeaderText = "Action";
tf.ItemTemplate = new AssignPage.MyTemplate(..., mylb);
GridView1.Columns.Add(tf);
protected void Page_PreInit(object sender, EventArgs e)
{
LinkButton lb = new LinkButton();
lb.Text = "AssignAll";
lb.Command += new CommandEventHandler(AssignAll_Click);
lb.CommandName = "XXX";
this.mylb = lb;
protected void AssignAll_Click(object sender, CommandEventArgs e)
{
string[] arg = new string[2]; // BREAK POINT HERE
arg = e.CommandArgument.ToString().Split(';');
...
...
Response.Redirect("BaseAndRepeats.aspx?id=" + r.Event.ID);
In the template class I have I have
LinkButton lb;
public MyTemplate(..., LinkButton _lb)
{
...
lb = _lb;
...
public void InstantiateIn(System.Web.UI.Control container)
{
...
...
// various conditional statements
lb.CommandArgument = mylist[rowCount].ReqtID.ToString() + ";" + mylist[rowCount].RotaUser;
container.Controls.Add(lb);
...
The break point in the handler is never reached
I thought I was creating the linkbutton in the right place
the linkbutton appears in the grid quite happily
when I click on the linkbutton there is a call
to Page_PreInit and to Page_Load and as I expected
it is a postback.
But AssignAll_Click is never called.
In the browser footer it shows "javascript: __dooPsotabck(..." when you hover
over the buttonlink
I believe the problem is this line:
lb.Command += new CommandEventHandler(AssignAll_Click);
Change it to:
lb.Command += AssignAll_Click;
Edit:
Also you want to move it from Page_PreInit to Page_Init but you may find more success with it in Page_Load (outside the IsPostBack). Here's an example that works for me:
On the ASPX page:
<asp:Panel ID="TestPanel" runat="server" />
Codebehind:
protected void Page_Init(object sender, EventArgs e)
{
//Init used because TestPanel doesn't exist yet
CreateTestButton();
}
private void CreateTestButton()
{
var lb = new LinkButton();
lb.Text = "hello";
lb.Command += lb_Command;
TestPanel.Controls.Add(lb);
}
void lb_Command(object sender, CommandEventArgs e)
{
throw new NotImplementedException();
}
Going over your code it looks like your adding another column into your GridView and creating a button inside that column for each row - but you've got the column being added on Page_Load and the button being created and bound to it before in Page_PreInit

Generic event handler not firing from dynamic buttons

I have a bunch of buttons being dynamically created and setting its click event to an event handler...When I run it they handler in never firing, I've stepped through the code and nothing seems out of the ordinary but it just won't fire.
Here is a snippet of the code where the button is being created..
for (cellCtr = 1; cellCtr <= 9; cellCtr++)
{
Button button = new Button();
HyperLink link = new HyperLink();
TableCell tCell = new TableCell();
if (rowCtr == rN)
break;
string myStr = daccess.dsSubjects.Tables[0].Rows[rowCtr]["SubjectName"].ToString();
int myID = Convert.ToInt32(daccess.dsSubjects.Tables[0].Rows[rowCtr]["SubjectID"].ToString());
button.ID = Convert.ToString(myID);
button.Text = myStr;
button.CssClass = "btn btn-primary btn-sm";
button.Click += ButtonSubjectClick;
tCell.Controls.Add(button);
tRow.Cells.Add(tCell);
rowCtr++;
if (cellCtr == rN)
{
rowCtr = rowCtr - 1;
break;
}
}
and here is the handler that's it suppose to call...
void ButtonSubjectClick(object sender, EventArgs e)
{
Button button = (Button)sender;
daccess.DeleteSubjects(Int32.Parse(button.ID.ToString()));
button.CssClass = "btn-active";
}
When its ran, the source looks like this
<input type="submit" name="38" value="Math" id="38" class="btn btn-primary btn-sm" />
This code works for me:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// do something if needed
}
// outside of postback, you need to add it each time
Button button = new Button();
button.ID = "btn1";
button.Text = "clicky me";
button.Click += new EventHandler(ButtonSubjectClick);
pnl.Controls.Add(button);
}
void ButtonSubjectClick(object sender, EventArgs e)
{
Button button = (Button)sender;
button.Text = "clicked me";
}
I believe it's a question about how are you adding your button to the page. I'm adding my button at each postback and it is thus registered by the server.
If you are adding your buttons in another event then you could use viewstate or session variables, store some kind of a flag to create the button and then check for this flag in each postback.
Edit, for the sake of clarity, pnl is a Panel on my page:
<form id="form1" runat="server">
<div>
<asp:Panel ID="pnl" runat="server"></asp:Panel>
</div>
</form>

EventHandler is not working for dynamic control

I have referred Error with the event handlers of dynamic linkbutton . It says to add event handlers in Page_Init or Page_Load. I tired following code. But the event handler is not fired when I click on the dynamic added link buttons. What need to be corrected here?
Note: The dynamic LinkButton controls are added in the click event of a button after some business validations (the business code is not given for brevity)
Markup
<form id="form1" runat="server">
<div>
<asp:LinkButton ID="lnkTest" runat="server" OnClick="LinkButton_Click">Static LinkButton</asp:LinkButton>
<br />
<asp:Button ID="btnAdd" runat="server" Text="Add" OnClick="btnAdd_Click" />
<br />
<asp:PlaceHolder ID="plhDynamicLinks" runat="server"></asp:PlaceHolder>
</div>
</form>
Code Behind
protected void Page_Load(object sender, EventArgs e)
{
foreach (Control ctrl in plhDynamicLinks.Controls)
{
LinkButton dynamicButton = (LinkButton)ctrl;
dynamicButton.Click += new EventHandler(LinkButton_Click);
}
if (Page.IsPostBack)
{
}
}
protected void Page_Init(object sender, EventArgs e)
{
int x = 0;
foreach (Control ctrl in plhDynamicLinks.Controls)
{
LinkButton dynamicButton = (LinkButton)ctrl;
dynamicButton.Click += new EventHandler(LinkButton_Click);
}
}
protected void LinkButton_Click(object sender, EventArgs e)
{
LinkButton clickedControl = (LinkButton)sender;
Response.Write(clickedControl.ID +" Link Button Clicked");
}
protected void btnAdd_Click(object sender, EventArgs e)
{
plhDynamicLinks.Controls.Clear();
LinkButton button1 = new LinkButton();
button1.ID = "D1";
button1.Text = "1";
plhDynamicLinks.Controls.Add(button1);
LinkButton button2 = new LinkButton();
button2.ID = "D2";
button2.Text = "2";
plhDynamicLinks.Controls.Add(button2);
}
It is mandatory to register all the required dynamic controls’ event handlers in the Page_Load/ Page_Init itself. One working example can be seen at Dynamic Control’s Event Handler’s Working
MarkUp
<form id="form1" runat="server">
<div>
<asp:Button ID="btnAdd" runat="server" Text="Add" OnClick="btnAdd_Click" />
<br />
<asp:PlaceHolder ID="plhDynamicLinks" runat="server"></asp:PlaceHolder>
</div>
</form>
CODE BEHIND
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
LinkButton lnk1 = new LinkButton();
lnk1.ID = "D1";
lnk1.Text = "A";
//Event handler must be registered in the Page_Load/Page_Init
lnk1.Click += new EventHandler(LinkButton_Click);
plhDynamicLinks.Controls.Add(lnk1);
LinkButton lnk2 = new LinkButton();
lnk2.ID = "D2";
lnk2.Text = "B";
lnk2.Click += new EventHandler(LinkButton_Click);
plhDynamicLinks.Controls.Add(lnk2);
LinkButton lnk3 = new LinkButton();
lnk3.ID = "D3";
lnk3.Text = "C";
lnk3.Click += new EventHandler(LinkButton_Click);
plhDynamicLinks.Controls.Add(lnk3);
LinkButton lnk4 = new LinkButton();
lnk4.ID = "D4";
lnk4.Text = "D";
lnk4.Click += new EventHandler(LinkButton_Click);
plhDynamicLinks.Controls.Add(lnk4);
}
}
protected void LinkButton_Click(object sender, EventArgs e)
{
PopulateLinksBasedOnCriteria();
LinkButton clickedControl = (LinkButton)sender;
Response.Write(DateTime.Now.ToString()+"___"+ clickedControl.ID + " Link Button Clicked" );
}
protected void btnAdd_Click(object sender, EventArgs e)
{
PopulateLinksBasedOnCriteria();
}
private void PopulateLinksBasedOnCriteria()
{
plhDynamicLinks.Controls.Clear();
if (DateTime.Now.Second < 30)
{
LinkButton linkButton1 = new LinkButton();
linkButton1.ID = "D1";
linkButton1.Text = "1";
plhDynamicLinks.Controls.Add(linkButton1);
LinkButton linkButton2 = new LinkButton();
linkButton2.ID = "D2";
linkButton2.Text = "2";
plhDynamicLinks.Controls.Add(linkButton2);
}
else
{
LinkButton linkButton3 = new LinkButton();
linkButton3.ID = "D3";
linkButton3.Text = "3";
plhDynamicLinks.Controls.Add(linkButton3);
LinkButton linkButton4 = new LinkButton();
linkButton4.ID = "D4";
linkButton4.Text = "4";
plhDynamicLinks.Controls.Add(linkButton4);
}
}
Dynamic controls must be re-created on every postback, this Article is a good link about how to persist dynamic controls and their state.
Add javascript onClick attribute to the dymanic control and set hidden field values which is required for the control event. Onclick of the dymanic grid, the will postback and will get the hidden field value. In page load call a method to do the job if the hidden field has value and make it null after doing the job.

dynamically created list of link buttons, link buttons not posting back

Hi I am dynamically creating link buttons in a 'ul li' list. I am then trying to tie each link button to a click event where i set a label to the text of the link button clicked. however the event that should fire doesnt get fired?
if (!Page.IsPostBack)
{
int listItemIds = 0;
foreach (Node productcolour in product.Children)
{
HtmlGenericControl li = new HtmlGenericControl("li");
LinkButton lnk = new LinkButton();
lnk.ID = "lnk" + listItemIds;
lnk.Text = productcolour.Name;
lnk.Click += new EventHandler(Clicked);
//lnk.Command += new CommandEventHandler(lnkColourAlternative_Click);
//lnk.Click
li.Controls.Add(lnk);
ul1.Controls.Add(li);
listItemIds++;
}
}
the above is wrapped within a if(!page.ispostback) and the label text is never set anywhere else.
heres to the event
protected void Clicked(object sender, EventArgs e)
{
LinkButton lno = sender as LinkButton;
litSelectedColour.Text = lno.Text;
}
Code must run on each postback:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
int listItemIds = 1;
for (int i = 0; i < 10; i++)
{
var li = new HtmlGenericControl("li");
var lnk = new LinkButton();
lnk.ID = "lnk" + listItemIds;
lnk.Text = "text" + i;
lnk.Click += Clicked;
//lnk.Command += new CommandEventHandler(lnkColourAlternative_Click);
//lnk.Click
li.Controls.Add(lnk);
ul1.Controls.Add(li);
listItemIds++;
}
}
private void Clicked(object sender, EventArgs e)
{
var btn = sender as LinkButton;
btn.Text = "Clicked";
}
Do this sort of thing OnInit and make sure you recreate the controls on every postback.
See this KB article for an example - a bit outdated but the methodology is still the same.

Categories

Resources