Dynamic LinkButton Click event never appears on the resulting anchor - c#

So I'm currently trying to add to each day of a .net calendar control one dynamic linkbutton (on the dayRender event). The problem I have is that the linkbutton href does not appear. It's not a problem of the linkbutton event not firing, the href= doesn't even appear, so it doesn't fire any postback. This means that the button looks like this in the html part:
<a class="delete79" ID="Delete_2014-09-01"> Delete </a>
My code looks like this:
protected void MyCalendar79_DayRender(object sender, DayRenderEventArgs e)
{
List<MenuDia> dayList = new List<MenuDia>();
foreach (var itemMenu in ListMenuDays)
{
if (itemMenu.Dia.CompareTo(e.Day.Date) == 0)
{
dayList.Add(itemMenu);
}
}
LinkButton deleteButton = new LinkButton();
deleteButton.CssClass = "delete79";
deleteButton.Text = "Delete";
deleteButton.ID = "Delete79_" + dayList[0].Dia.ToString("yyyy-MM-dd");
deleteButton.Click += delegate(object o, System.EventArgs a)
{
//simple stuff here, tried putting simple generic response.redirect
//and stuff like that but it wasn't the problem
};
}
I don't wanna sound rude but don't tell me that it's because I'm using a delegate instead of an eventhandler. First of all I tried changing that already (same thing happened) and second I usually do it like this when it's super simple so I don't have to create a separate method.
Also, I've tried changing the ID to something more predictable (Delete_+a simple index), that's not the problem unfortunately =(.
Any other ideas? Maybe it's because I'm doing it on dayrender and you can't do it there? How can I achieve the same thing then?

So yeah I found the problem. MSDN page says:
Because the DayRender event is raised while the Calendar control is
being rendered, you cannot add a control that can also raise an event,
such as LinkButton. You can only add static controls, such as
System.Web.UI.LiteralControl, Label, Image, and HyperLink.
That's the problem. I will do a hack manually that generates the same postback of a hidden linkbutton. Thanks everyone!

Related

ASP.NET C# Issue Adding event handler to ImageButton CodeBehind

I'm having problems adding an event to an ImageButton. I have to create a set of buttons depending on a selected option from a DropDownList. The buttons are created successfully with Database data, but I'm can't attach the OnClick functionality.
The created buttons must share the same Handler.
protected void cmbServ_SelectedIndexChanged(object sender, EventArgs e) {
ServiceID = cmbServ.SelectedValue.ToString();
ServiceName = cmbServ.SelectedItem.ToString();
DataTable dtFirstTab = new DataTable();
dtFirstTab = mySQLConn.getTable(qryCarry); // LOAD DATA FROM DB
foreach (DataRow row in dtFirstTab.Rows) {
FTabBtn = "btn"+(Convert.ToInt32(row["SKU_Credito"])).ToString();
FTabIconURL = row["SKU_Icon"].ToString();
Panel dvFirstTab = new Panel();
dvFirstTab.CssClass = "col-xs-2";
ImageButton IB = new ImageButton();
IB.ID = FTabBtn;
IB.ImageUrl = FTabIconURL;
IB.Click += new ImageClickEventHandler(btnX_click); // <-- PROBLEM
dvFirstTab.Controls.Add(IB);
pnlIcons.Controls.Add(dvFirstTab); // pnlIcons exists in HTML
}
protected void btnX_click(object sender, ImageClickEventArgs e) {
string Obj = ((ImageButton)sender).ClientID;
Cantidad = Convert.ToInt32(Obj.Substring(3, (Obj.Length) - 3));
txtMonto.Text = "$" + Cantidad.ToString();
}
All the buttons appear correctly, but when I click on them they just fire a "submit" action, acting like there's no OnClick assigned.
No CodeBehid example:
If I add this line in HTML (I removed asp tags)
ImageButton ID="btn10" runat="server" ImageUrl="MontoLogo_10ST.png" OnClick="btnX_click"
It does work as intended.
Any ideas? Thanks a lot!
Creating controls dynamically in ASP.NET webforms usually seems easy at the beginning, but problems are very common when it comes to handling events. Even if you assign your event handler correctly, the event handler is not run in a postback until you re-create all the dynamic controls early in page lifecycle. This explains why the sample with the ImageButton on the ASPX works whereas the dynamically created buttons don't.
See this page for details on creating controls dynamically. The most important part is the warning that basically says: if you need to add dynamic controls, better don't.
Usually you can find a way to create all the necessary controls in markup, for instance using a Repeater control. The big advantage of the repeater is that you have control about the markup that is created.
The following sample outlines the necessary steps:
Place a repeater on your aspx-page. If pnlIcons serves no other purpose than being the container for the dynamically created buttons, substitute it by the repeater. Use the Header- and FooterTemplate properties to add the markup that surrounds the ImageButtons (e.g. the div for dvFirstTab).
Think about which data you need to assign to the image button. In your case, the fields "SKU_Credito" and "SKU_Icon" seem to be required.
Place the Image button in the ItemTemplate of the repeater and bind the properties "Id" and "ImageUrl" to the corresponding fields.
Add a Command event handler and bind the CommandArgument property to a value that helps you discern between the image buttons.
In the command event handler, you can use the CommandArgument to discover which button has been clicked. Add the appropriate code that handles the command.
In the SelectedIndexChanged event handler, read the data from the database and bind the repeater to the result. This creates the rows in the repeater with the ImageButtons.
Ok, I've found the reason. The event handling must be assigned in Page_Load event, so I moved everything inside a method and called it from Page_Load, calling it from "SelectedIndexChanged" doesn't work . It's working now.
Thanks!

ASP.NET Click event does not work for multi buttons what created in tab button control

I am new in ASP.NET and I have a problem..
In my code, btn.Click event does not work for multi buttons what created in tab button control. Can you guys advice me?
Thanks,
<asp:Button Text="TAB MENU" BorderStyle="None" ID="Tab" CssClass="Initial" runat="server" OnClick="Tab_Click" />
<asp:Panel ID="panel1" runat="server" Direction="LeftToRight" HorizontalAlign="Left"></asp:Panel>
protected void Tab_Click(object sender, EventArgs e) {
foreach (...) {
Button btn = new Button();
btn.Click += Button1_Click;
panel1.Controls.Add(btn);
}
}
protected void Button1_Click(object sender, EventArgs e) {
**some code here! but does not work.**
}
Try this
Button btn = new Button();
btn.Click += new RoutedEventHandler(Button1_Click);
panel1.Controls.Add(btn);
Your problem probably lies along the lines of the fact that the button does not exist when the Button1_Click callback is fired... Asp.net webforms is a somewhat leaky abstraction over HTTP, and therefore it's a bit tough to decipher sometimes, but I expect what is happening is that when the postback from your button click occurs, the button doesn't actually EXIST in the control tree, because that button only gets added to the control tree when a tab control is clicked. So because the button does not exist on the postback, webforms doesn't know what to do with the event, so it ignores it...
If your buttons must be created dynamically, consider making them do some javascript to edit some hidden field or something, the value of which you can inspect in the Page_Load method, and then do whatever you want to do functionality-wise with that value.
If they are NOT dynamic, and instead will be the same for each page load (but different for each tab - ie, when the page is loaded, you're drawing some info from a db to decide what buttons to display, but that will not change from postback to postback of the same page), then consider creating the buttons in the Page_Load event instead of inside the event that is raised when the tab is created.
ALTERNATIVELY, since in your comment you suggest that the buttons will be used to open a new window, why not just make the buttons do that client side, ie with javascript window.open commands. Then you don't even need to postback to the server at all...

How to set a link's NavigateUrl on link onClick?

I'm creating a link dynamically. The NavigateUrlproperty of the link is set on a call to a method. But I don't want to call the method before the link is clicked because there are so many of such links.
Any help on how to do it is appreciated. Thanks.
public void CreateLink()
{
LinkButton link = new LinkButton();
link.Click += new EventHandler(link_Click);
string key = GetKey();
}
private void link_Click(object sender, EventArgs e)
{
var url = GetLinkUrl(e.???);
Response.Redirect(url);
}
public string GetLinkUrl(string key)
{
//do things to retrieve url
return url;
}
Update: Many thanks, all :) I am going to use LinkButton, as seen in updated code above.
But I forgot to ask: There is a key associated with each link which is needed to get the URL. How can I
What you're doing is potentially quite complex; you would need to output back to the client something indicating a call to a code-behind method to be executed before the navigation occurs, for example:
HyperLink link = new HyperLink();
link.Attributes.Add("onclick", "doClientsideCode();");
...
Then, a bit of JavaScript:
function doClientsideCode() {
// Do a call to a service or similar, to run the method you're wanting to run.
// This will then do the navigation you require.
}
Thus, my suggestion would actually be a LinkButton; this will fire an event that you can capture server-side, via something similar to:
public void link_Click(object sender, EventArgs e) {
// Run my method
// Issue response.redirect to correct URL.
}
[Edit - in answer to the edited question, you have access to the properties CommandName and CommandArgument when using a LinkButton which should do what you require. However, I do feel that that part should now be a separate question.]
One alternative is to use an ASP button instead of Hyperlink, and bind the GetLinkUrl function inside a click handler for the button. Then run Response.Redirect('yourURL') to execute the link.
EDIT: As Adrian said above, a LinkButton will be the best of both worlds - it is styled like a Hyperlink, but you can set a click handler for it to get the URL dynamically, only when the button is actually clicked.

LinkButton postback but click event not fired

Hi everyoneThis is my first post on stackoverflow (which btw is by far my favourite site for finding answers). After finally admitting defeat, I'm hoping someone can help me with this problem...
The question has already been asked several times, but none of the suggested solutions I found has helped. Apologies in advance for a lengthy post, but I want to avoid anyone wasting their time on suggesting things I tried already.
The code below worked until recently, and its structure has not been touched since (although unrelated changes were made to the child page). In any event, it suddenly stopped working. Now even the most simplified button won’t fire.
Setup
VS 2008 C#, IIS 7 (no changes in setup since way before it stopped working)
nested masterpage (main + 1 child)
dynamically loaded ucl with datalist in child page
(i.e. MP => nested MP => child page => ucl => datalist => linkbutton)
linkbutton click event also resides in ucl
Problem
On LB click, the postback occurs ok, but the server-side click event never gets hit.
Code
page:
var ctrlX = base.LoadControl("~/somedir/someucl.ascx");
=> loads fine
ascx file (datalist stripped of all but the button):
<asp:DataList ID="dlX" RepeatLayout="Table" runat="server">
<HeaderTemplate></HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<asp:LinkButton ID="btnX" OnClick="btnX_Click" CausesValidation="false" runat="server" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate></FooterTemplate>
codebehind:
protected void btnX_Click(object sender, EventArgs e)
{
// do something
}
things tried
cleaning the solution
digging out a working backup and checking for code changes
(found none affecting the structure or user control)
setting LinkButton CausesValidation true/false
stripping datalist and LinkButton down to bare essentials
adding AddressOf="btnX.click" to LinkButton
wrapping UpdatePanel one at a time with varying settings around usercontrol datalist linkbutton
reattaching eventhandler in usercontrol init / load event:
IEnumerable<Control> controls = Utils.FlattenChildren(dlX);
foreach (var button in controls.OfType(LinkButton)())
{
if (button.ID.Contains("btnX"))
button.Click += new EventHandler(btnX_Click);
}
Wherever I add above code, all buttons are found and the event is attached, but click event doesn't fire ((LinkButton) = LinkButton inside <>; couldn't get it to display right, still struggling a bit with the editor)
.
adding PostBackUrl manually in page load event
comparing the client ids between load/postback events
=> they always match
That's it. Right now, I can't think of what else to try or check (maybe something in the breakpoint context menu on postback?).
Because the ucl loads fine, and the postback is working ok, I suspect the problem is somewhere in the ucl, rather than the child page loading it. But maybe not.
If at all possible, I want to avoid workarounds (I need the button command argument, not shown above, and am not keen on solutions such as jquery with hidden field or query string).
Apart from anything, I would really like to understand what causes this.
Obviously, I'm missing something... Thanks to anyone taking their time reading/helping with this!
======== as requested additional codebehind =======
I've simplified the parent page code to a minimum, dropping all method calls, and as per Eoins suggestion moved the ucl load in the page's init event. The ucl code remains as shown above. The DL and LB show up fine, and on click the postback is triggered, ucl page load event is hit, but as before, the server click event is not hit.
protected override void OnInit(EventArgs e)
{
var ctrlX = base.LoadControl("~/someucl.ascx");
if (ctrlX == null)
return;
DataList dlX = (DataList)ctrlX.FindControl("dlX");
if (dlX == null)
return;
DummyCollection x = new DummyCollection();
x.Add(null); // ok since the test LB does not draw on the datasource
dlX.DataSource = x;
dlX.DataBind();
pnlX.Controls.Add(ctrlX);
base.OnInit(e);
}
var ctrlX = base.LoadControl("~/somedir/someucl.ascx");
Where exactly does this code live on your page?
You'll need to make sure you're creating it and adding it to the control collection early enough in the page lifecycle so that on subsequent postbacks its created & wired up in time. I.e. in the oninit event.
protected override OnInit(...)
{
base.OnInit(...);
var ctrlX = base.LoadControl("~/somedir/someucl.ascx");
this.Controls.Add(ctrlX);
}

Asp.NET Server Control Postback

I have a Control I want to create. Here's a simple example of what I was to accomplish.
I want the control to contain a button.
Button b = new Button();
b.Text = "Test";
b.Click += new EventHandler(b_Click);
this.Controls.Add(b);
Now, the control renders fine, the button shows up on the page. The heart of the problem I'm having is that the b_Click Event Handler is never triggered.
protected void b_Click(object sender, EventArgs e)
{
throw new NotImplementedException();
}
Any help here would be much appreciated. I don't want to use a User Control here for purely selfish reasons and would like to totally encapsulate this in a single DLL.
Thanks In Advance.
EDIT**
namespace ClassLibrary1
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:WebCustomControl1 runat=server></{0}:WebCustomControl1>")]
public class WebCustomControl1 : WebControl
{
protected override void CreateChildControls()
{
Button b = new Button();
b.ID = "button";
b.Text = "Click Me";
b.Click += new EventHandler(b_Click);
this.Controls.Add(b);
base.CreateChildControls();
}
protected void b_Click(object sender, EventArgs e)
{
this.Controls.Add(new LiteralControl("<p>Click!</p>"));
}
}
}
So from the comments I've tried this. The simplest of exampes, still no go. Is there something I'm fundamentally missing?
public class WebCustomControl1 : WebControl
needed to be
public class WebCustomControl1 : WebControl, INamingContainer
that's it. that's all that was needed to make this postback issue work.
Override the CreateChildControls method and create/add the button (and register the handler) in that method.
Using OnInit/OnLoad to create controls like this is incorrect and will lead to inconsistent behavior (such as what you're experiencing).
Edit: You might also try setting button.ID so that it's the same on every postback, it's possible the raised event isn't seeing it for that reason.
Please show the definition of your control class.
Does your control inherit from Control, WebControl, or CompositeControl. Try inheriting from CompositeControl and see if that helps.
So your button renders to the page correctly and causes a postback when the user clicks it, but the OnClick code never runs?
Remember, whenever you do a postback you're working with a brand new instance of your page class. Part of the postback process is running whatever event was triggered by the user. For this to happen, the asp.net processor needs to know about the event at a specific point in the page lifecycle. At this point, your button must already be on the page with the event handler registered. If this doesn't happen, your event won't fire. Try moving your button creation up earlier in the page lifecycle.
This may be the case of assigning the handlers well after the event is raised.
My common practice when dealing with controls are:
Use Control.Init event to initialize everything (default text, handlers, size, composition, etc.) and also initialize the child controls.
Use Control.Load event to handle any data binding operation (based on the properties/fields set during the Init event).
Check the identifier of the button control before the postback and after the postback. If it's not the same, it won't work.
You can overwrite the identifier yourself if needed.

Categories

Resources