Custom Image Button control click handler not firing - asp.net

I've got a bit of an issue with creating a new control based on ASP.NET's ImageButton control. Everything works as expected, except for the click handler that is being hooked up in the control's OnInit override. Basically, clicking the custom image button just refreshes the page, never hitting the handler.
Now, I know this is something stupid I've done or just not understood, but I can't for the life of me figure this out. All the articles, questions and forum posts I've found on event handling issues for controls is for child controls, rather than ones that inherit from existing control types and have their own predefined handlers.
The following code is what I've written:
public class WebPaymentButton : ImageButton
{
public string DisabledImageUrl { get; set; }
public string TermsAcceptClass { get; set; }
protected override void OnPreRender(EventArgs e)
{
Page.ClientScript.RegisterClientScriptResource(typeof (WebPaymentButton), "PaymentModule.Scripts.WebPaymentButtonScript.js");
}
protected override void OnInit(EventArgs e)
{
CssClass = "WebPaymentButton";
if (!string.IsNullOrWhiteSpace(TermsAcceptClass))
{
Attributes["data-TermsClass"] = TermsAcceptClass;
}
if (!string.IsNullOrWhiteSpace(DisabledImageUrl))
{
Attributes["data-DisabledImageUrl"] = ResolveUrl(DisabledImageUrl);
}
Click += WebPaymentButton_Click;
base.OnInit(e);
}
private void WebPaymentButton_Click(object sender, ImageClickEventArgs e)
{
HttpContext.Current.Response.Redirect("http://dummy_payment_page_in_place_of_code", true);
}
}
I've tried hooking the handler up in the OnLoad and also switching it to run after the base.OnInit/OnLoad calls. Nothing has solved the handler issue. Can anyone point me in the right direction?
In case it helps, here is the markup for the button on the page:
<pm:WebPaymentButton runat="server" ImageUrl="~/pay-now.png" DisabledImageUrl="~/not-pay-now.png" TermsAcceptClass="TermsCheckbox" ID="MainPayButton" />

Have you tried overriding the OnClick event handler instead of hooking up to a new event handler?
Remove the Click += WebPaymentButton_Click line from OnInit and remove the WebPaymentButton_Click function, then add the following code to your class instead:
protected override void OnClick(ImageClickEventArgs e)
{
base.OnClick(e);
HttpContext.Current.Response.Redirect("http://dummy_payment_page_in_place_of_code", true);
}

Related

can httphandler fire an event?

I want to check Session in some pages. To do this I am adding the page names which I want to check inside web.config as a appsetting key.
I want to use httpHandler with firing an event after it finds the session is empty or something else.
If I create httpHandler as a dll(another project) and add to a web site, can handler fire an event and web site capture it inside a web page?
What you can do is this:
Your HttpHandler puts a value in the HttpContext.Current.Items collection telling if there was Session or not. Something like
HttpContext.Current.Items.Add("SessionWasThere") = true;
You create a BasePage that checks that value in the Page_Load event and raises a new event telling so:
public abstract class BasePage : Page {
public event EventHandler NoSession;
protected override void OnLoad(EventArgs e){
var sessionWasThere = (bool)HttpContext.Current.Items.Add("SessionWasThere");
if(!sessionWasThere && NoSession != null)
NoSession(this, EventArgs.Empty);
}
}
In your page, you suscribe to that event:
public class MyPage : BasePage{
protected override void OnInit(){
NoSession += Page_NoSession;
}
private void Page_NoSession(object sender, EventArgs e) {
//...
}
}

.NET Public Events not wiring up in nested web user controls

I have C# Web Application that has an aspx page hosting a user control (Review.ascx). Inside that user control there are 5 more user controls, one of which has a public event (Review_Summary.ascx). The problem is no matter what i do I cannot get the event wired up in the parent ascx control (Review.ascx).
Here is what I have in the child control (Review_Summary.ascx)
public event EventHandler forwardStatusChanged;
#region methods
protected void btnForward_Click(object sender, EventArgs e)
{
if (btnForward.Text == "Return")
{
if (forwardStatusChanged != null)
{
forwardStatusChanged(sender, e);
}
removeForward();
}
}
In the parent control (Review.ascx) I have this
public void initReview(string EmployeeNumber)
{
RevSummary.forwardStatusChanged += new EventHandler(RevSummary_forwardStatusChanged);
<more code here>
}
protected void RevSummary_forwardStatusChanged(object sender, EventArgs e)
{
lblReadOnly.Visible = false;
}
RevSummary is the ID of the child control in the parent control. InitReveiw is a method that is called by the aspx page in its Page_Load event.
I get no errors on compile or at runtime. But when I click the button the forwardStatusChanged event is null. The "removeForward()" method that is called after that executes properly. So that fact that the event is always null leads me to believe that the wire up in the parent control is not working. However, I am sure it is executing becasue all of the code after that executes.
How can I figure out why this event is not wiring up?
Where is initReview being called from? Are you sure it's being called because the only reason this happens is that the event handler wasn't truly setup. I've never found a reason other than this, the several times I did this myself.
HTH.

Can I bubble up event from Master page to ASPX

Can I bubble up a button click event of a button in master page to be handled by an event handler in the aspx page ?
You can expose the event handler and hookup to it, like this:
In the master:
public event EventHandler ButtonClick
{
add { ButtonThatGetsClicked.Click += value; }
remove { ButtonThatGetsClicked.Click -= value; }
}
In the page:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
((MyMasterType)Master).ButtonClick += MyHandler;
}
private void MyHandler(object sender, EventArgs e)
{
//Do Something
}
Also, you can avoid the Master type cast and have it already appear in intellisense as your Master's type by using the #MasterType directive in the aspx markup.
You can rebroadcast the event. Declare a new corresponding event in your master page, such as HelpClicked and then aspx pages that use this master can subscribe to the event and handle it appropriately. The master can also take a default action if there are no subscribers (or use an EventArgs with a Handled property or something like that).

ASP.NET dynamically reassign controls in the control tree

Let's say I have a custom control that looks like this
<cc:MyControl runat="server" ID="myc" LinkControlID="NewParent" />
and, on the same page:
<asp:TextBox runat="server" ID="NewParent" />
What I would like to do is, from MyControl, change NewParent's parent so that it would be part of MyControl's Controls collection. When I try to do this, from OnInit, I get:
The control collection cannot be modified during DataBind, Init, Load, PreRender or Unload phases.
Which makes sense, but is there a way around this? I'm OK if NewParent remains the child of the Page as long as from MyControl I can somehow redirect the rendering to MyControl's control.
Can this be done? Thanks.
EDIT:
To clarify here's a mockup of MyControl:
public class MyControl : Panel
{
protected override void OnInit(System.EventArgs e)
{
base.OnInit(e);
if (!String.IsNullOrEmpty(LinkControlID))
{
Control link = Parent.FindControl(LinkControlID);
if (link != null)
{
Controls.Add(link);
}
}
}
public string LinkControlID { get; set; }
}
This assumes that MyControl and LinkControlID are placed on the same level in the tree hierarchy, which is OK in my case.
why don't you try adding it in Page_LoadComplete
myc.Controls.Add(NewParent);
I couldn't reproduce it, but as aman.tur suggested, have you tried another event? Overriding CreateChildControls() seems like the right place for it.
#TheVillageIdiot's suggestion worked for me:
protected void Page_Init(object sender, EventArgs e)
{
Page.LoadComplete += Page_LoadComplete;
}
private void Page_LoadComplete(object sender, EventArgs e)
{
if (InHeader)
{
Page.Header.Controls.Add(this);
}
}
Mind you, I had different requirements, but I don't think it should be much of an issue if you can access the new parent control from within your MyControl. The general format is to add an event listener on the Page to make changes on LoadComplete.

Pass data to user components in asp.net

It is .net 2.0 here, not MVC, and I am crap at asp forms.
I have a page with user controls on it. When I click on something in the page, I want to load the usercontrol based on a parameter from the page.
I cannot do it.
In my page's FaultTree_Clicked, I get the value, then:
I tried exposing a property on the
child user control to set the value, which i set in FaultTree_Clicked,
it gets forgotten.
I tried saving it to
Session["mykey"], and loading
Session["mykey"] in the control's
Page_init... the value is blank.
I tried saving it to
ViewState["mykey"], and loading
ViewState["mykey"] in the control's
Page_init... the value is blank.
EDIT: more specific info:
Here is a cut down version of what the page(MyFault) looks like:
<form id="form" runat="server">
<div id="faulttree">
<asp:TreeView ID="FaultTree" ......>
</div>
<uc1:_DefectDetail ID="DefectDetail" runat="server" Visible="true" EnableViewState="true" />
</form>
And there is a method on the pages code behind "FaultTree_SelectedNodeChanged()".
When that method is hit, I want to load/show the DefectDetail control. The DefectControl requires a faultid, which comes off the Tree, which I successfully get in the SelectedNodeChanged method. I cannot get the faultid into the defect control.
This has to do with ASP.NET page lifecycle. By the time the click event fires, the control's init event has already happened.
In order to better assist you, please provide a more detailed explanation of what the FaultTree control is, what is the desired result and some sample code.
UPDATE:
Instead of a public property, you can simply create a public method in the control that does the desired action and invoke it from the FaultTree_SelectedNodeChangeEvent.
Example (for a public method named Refresh):
_DefectDetail.Refresh(object data);
Basically you have to use EventHandlers....
1. Add a event handler to your user control (I had a search bar UscSearchCriteriaBar1)
public event EventHandler CriteriaChanged;
+
private void InternalOnCriteriaChanged()
{
OnCriteriaChanged();
}
+
protected virtual void OnCriteriaChanged()
{
// If there are registered clients raise event
if (CriteriaChanged != null)
CriteriaChanged(this, EventArgs.Empty);
}
+
Example
public int EmployeeID
{
get
{
f (Session["EmployeeID"] != null)
{
ViewState["EmployeeID"] = Convert.ToInt32(Session["EmployeeID"]);
}
if (ViewState["EmployeeID"] == null)
ViewState["EmployeeID"] = 0;
return int.Parse(ViewState["EmployeeID"].ToString());
}
set
{
ctlEmployee.SelectedValue = value.ToString();
ViewState["EmployeeID"] = value;
Session["EmployeeID"] = value;
}
}
In your page or other control
override protected void OnInit(EventArgs e)
{
InitializeComponent();
UscSearchCriteriaBar1.CriteriaChanged += new EventHandler(this.CriteriaChanged);
base.OnInit(e);
}
private void CriteriaChanged(object sender, EventArgs e)
{
try
{
RefreshData();
}
catch (Exception ex)
{
ExceptionManager.Publish(ex);
}
}
You can get UscSearchCriteriaBar1.EmployeeID
This code should give you some ideas...was done for 1.1 should work on 2.

Resources