1

Can a usercontrol (child, doesStuff.ascx) page react to an event from Page (parent, page.aspx)? I have a button on the parent page. Onclick i'd like to fire an event on the child.

doesStuff.ascx:

//something like this

((doesStuff)this.Page).someButtonControl.click;

// or

something.Click += new EventHandler(someReference???);
Jim VanPetten
  • 413
  • 3
  • 11

2 Answers2

2

Child to Parent Bubble Up

If you want to pass argument from child control to parent, you can use CommandEventHandler.

Parent ASPX

<%@ Register Src="~/DoesStuff.ascx" TagPrefix="uc1" TagName="DoesStuff" %>    
<!DOCTYPE html>    
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
    <form id="form1" runat="server">
        <uc1:DoesStuff runat="server" ID="DoesStuff"
            OnChildButtonClicked="DoesStuff_ChildButtonClicked" />
    </form>
</body>
</html>

Parent Code Behind

public partial class Parent : System.Web.UI.Page
{
    protected void DoesStuff_ChildButtonClicked(object sender, EventArgs e) { }
}

Child ASCX

<asp:Button ID="BubbleUpButton" runat="server" 
    Text="Bubble Up to Parent" 
    OnClick="BubbleUpButton_OnClick" />

Child Code Behind

public partial class DoesStuff : System.Web.UI.UserControl
{
    public event EventHandler ChildButtonClicked = delegate { };

    protected void BubbleUpButton_OnClick(object sender, EventArgs e)
    {
        // bubble up the event to parent. 
        ChildButtonClicked(this, new EventArgs());
    }
}

Parent to Child

It is not a good practice in ASP.Net Web Form to calling one event to another event without underlying control.

Instead, you want to create a public method, and call it from Parent. For example,

// Parent
public partial class Parent : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        var doesStuff = DoesStuff1 as DoesStuff;
        if (doesStuff != null) DoesStuff1.DisplayMessage("Hello from Parent!");
    }
}

// Child
public partial class DoesStuff : System.Web.UI.UserControl
{
    public void DisplayMessage(string message)
    {
        ChildLabel.Text = message;
    }
}
Community
  • 1
  • 1
Win
  • 61,100
  • 13
  • 102
  • 181
  • Win, this is a very good example of Bubble "Up". Can this be reversed? Bubble Down? My event happens in the parent, and the method to call is in the child. Also, my usercontrol (child pages) are added dynamically container.Controls.Add("container/location.ascx) – Jim VanPetten Feb 06 '17 at 15:57
  • Thanks for your time Win. Let me get more specific. I have a button on Page/Parent to log-off. When they click that button i want to call a method in the usercontrol to save the data: public void FinishBatchButton_Click(object sender, EventArgs e) – Jim VanPetten Feb 06 '17 at 16:19
  • Rather than calling `FinishBatchButton_Click` directly from parent, you need to create a public method and move codes inside `FinishBatchButton_Click` to new method. Then let both `FinishBatchButton_Click` and `LogoutButton_Click` *(located inside parent)* call the newly created method. *Again, do not make a fake call from one event to another event in ASP.Net Web Form; it will end up with disaster if someone later decides to use that user control elsewhere.* – Win Feb 06 '17 at 16:27
  • For Clarification: the second "event" is just the name of a method. On the usercontrol page the operator has an option of clicking a save button which calls the method FinishBatchButton_Click. If he forgets and logs off by clicking logoff button on parent i need to save by calling the FinishBatchButton_Click method on the usercontrol. – Jim VanPetten Feb 06 '17 at 16:36
  • Do you think people click on ***LogOff*** button to logoff from web application? *I normally log users activities in my web applications; 99% just close their browser.* If you are working on that feature, I'm sorry to say that you are on wrong track. – Win Feb 06 '17 at 16:40
  • In my application i have a logout button: protected void LogMeOut(object sender, EventArgs e) { try { Session.Clear(); Session.Abandon(); Response.Cache.SetExpires(DateTime.UtcNow.AddMinutes(-1)); Response.Cache.SetCacheability(HttpCacheability.NoCache); Response.Cache.SetNoStore(); We have multiple users on each machine – Jim VanPetten Feb 06 '17 at 16:43
  • i'd like to save the form when they logout – Jim VanPetten Feb 06 '17 at 16:43
  • 1
    Auto saving is a lot of work in browser close. Instead, keep track of the changes, and prompt a message either Logout Button click or browser close - For example, in jQuery - `$( window ).unload(function() { return "Are you sure you want to navigate away from this page without saving changes"; });`, and [Best way to intercept a Button postback](http://stackoverflow.com/questions/17578379/best-way-to-intercept-a-button-postback/17579534#17579534) – Win Feb 06 '17 at 16:48
  • Ohh, that gives me an idea. I can use jquery to trigger click my existing save button on the usercontrol. OMG that works. Thanks for the jquery thought. How do i mark your answer for credit? – Jim VanPetten Feb 06 '17 at 17:29
1

If i truly understand you, You can use delegate to this purpose. In user control uc1:

    public Action action;
    protected void btnSubmit_Click(object sender, EventArgs e)
    {
        action();
    }

And in the page:

protected void Page_Load(object sender, EventArgs e)
    {
        uc1.action = someAction;
    }

    public void someAction()
    {
        //Do Some thing
    }
Farzin Kanzi
  • 3,380
  • 2
  • 21
  • 23
  • Thak you Farzin but i think you got it backward. I want a click event from the page to trigger a method in the usercontrol. In otherwords (to be more specific) in my parent/master/Page i have a switchuser button. When they click i want the usercontrol to updateAllrecords(); So, button is in the Page and action is in the usercontrol. – Jim VanPetten Feb 05 '17 at 21:53
  • So why you dont create a public method `public void update()` in user control and in the page fire it? in page: `uc1.update()` – Farzin Kanzi Feb 05 '17 at 21:57
  • Hi Farzin, i did try that and it seems the page life-cycle is in the wrong state. Lots of null errors in the usercontrol when fired like that: Controls.Workflow.Racking ucRacking = (Controls.Workflow.Racking)Page.LoadControl("~/Controls/Workflow/Racking.ascx");ucRacking.FinishBatchButton_Click(null, null); – Jim VanPetten Feb 05 '17 at 22:04
  • I wonder if referencing the uc (Workflow/Racking) the way i do causes the issue? – Jim VanPetten Feb 05 '17 at 22:08
  • Maybe FindControl() instead of LoadControl? – Jim VanPetten Feb 05 '17 at 22:09
  • How did you add your user control to page? by code behind or by tag? – Farzin Kanzi Feb 05 '17 at 22:11
  • I just debugged FindControl() and the usercontrol is totally null--wrong view state (pre_render would find it, but how to pre_render_click???) – Jim VanPetten Feb 05 '17 at 22:13
  • One more thing: your idea of uc1.update(), my usercontrol pages are added dynamically so they are not strongly typed/referenced. So my ucpage has to be found() – Jim VanPetten Feb 05 '17 at 22:16
  • After load control, did you added that to page? `Control uc1 = LoadControl("~/Controls/Work‌​flow/Racking.ascx");This.Controls.Add(uc1)` – Farzin Kanzi Feb 05 '17 at 22:18
  • string controlLocation = string.Format("~/Controls/{0}.ascx", widget.ControlName.Replace(".", "/").Replace(" ", "")); var plc = Page.LoadControl(controlLocation); plc.ID = widget.ControlName.Replace(".", "_").Replace(" ", ""); container.Controls.Add(plc); //in this case the id would be "Workflow_Racking" – Jim VanPetten Feb 05 '17 at 22:25
  • So, in a sense yes i added it as you say but i had to programmatically add the id as well. Intellesense wont recognize "Workflow_Racking" of course. – Jim VanPetten Feb 05 '17 at 22:26
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/134929/discussion-between-farzin-kanzi-and-jim-vanpetten). – Farzin Kanzi Feb 05 '17 at 22:29