Solved

Use of delegates in ASP.NET user controls

Posted on 2010-11-11
16
466 Views
Last Modified: 2012-05-10
Dear Experts,

I have a "save" button on an ASP.net web user control which saves some form data.

Within this control is another user control, designed to navigate through records.

When the user presses on a button on the nested user control, I'd like the "save" method on the first ASCX to be called, thus saving the form data before traversing to the next record.

I understand that I'll probably need to use delegates to achieve this, however am would appreciate it if somebody could give me some clarification or advice on how to achieve this.

My navigation buttons on my nested control are hyperlinks which have URLs generated by some business logic.

Any advice would be appreciated.

Nick
0
Comment
Question by:nkewney
  • 8
  • 6
  • 2
16 Comments
 
LVL 18

Expert Comment

by:Richard Lee
ID: 34110611
A simplier approach would be something like this:

DaTribe
public interface ISave
{
   void Save();
}

// This is the page which holds the user control
public class ParentPage : System.Web.UI.Page, ISave
{
}

// This is the usercontrol
public class InnerControl : System.Web.UI.UserControl
{
    public void ButtonClick(object sender, EventArgs e)
    {
        if(Parent is ISave)
        {
            var parent = Parent as ISave;
            parent.Save();

            // Do something else
        }
    }
}

Open in new window

0
 
LVL 1

Author Comment

by:nkewney
ID: 34110648
Hi DaTribe,

Thanks for the tip.

Since it's two user controls, how would this work?

--> I now have this on the control with "save" method

    Public Interface ISave
        Sub EditLead()
    End Interface

I'm just unclear on where to implement this interface?

Nick
0
 
LVL 18

Expert Comment

by:Richard Lee
ID: 34110763
Ok lets try again, follow closely ;)

DaTribe
public interface ISave
{
   void Save();
}

public interface IParentPage
{
   ISave SaveControl { get; }
}


// This is the page which holds the user control
public class ParentPage : System.Web.UI.Page, IParentPage
{
   public ISave SaveControl 
   {
      // This returns the actual usercontrol but 
      // restricts access to the interface methods
      get { return SaveUserControl as ISave; } 
   }
}

// This is the usercontrol with save button
public class SaveUserControl : System.Web.UI.UserControl, ISave
{
   public void Save()
   {
   }
}

// This is the usercontrol with grid
public class GridUserControl : System.Web.UI.UserControl
{
    public void ButtonClick(object sender, EventArgs e)
    {
        if(Parent is IParentPage)
        {
            var parent = Parent as IParentPage;

            if(parent.SaveController != null)
               parent.SaveController.Save();

            // Do something else
        }
    }
}

Open in new window

0
 
LVL 1

Author Comment

by:nkewney
ID: 34111106
Hi DaTribe,

I really appreciate your help, but am slightly confused :)

I'm possibly being completely thick here, but I have three pages:

- Default.aspx (page holding my Profile user control with the "save" method")
- Profile.ascx (holding my navigator user control)
- Navigator.ascx (with the buttons I'd like to control the "save" method on my Profile.ascx)

My understanding is:

Default.aspx
=======================
Public Interface ISave
    Sub Save()
End Interface

Public Interface IParentPage
    ReadOnly Property SaveControl() As ISave
End Interface

Partial Public Class DefaultPage
    Inherits System.Web.UI.Page, IParentPage (can only specify one in class?!)

Nick
0
 
LVL 18

Expert Comment

by:Richard Lee
ID: 34111236
So the referencing mechanism I am trying to achieve in visual form is:

Default.aspx
--------------------------------------
|                                                   |
|       Profile.ascx                            |<-- |
|       ---------------------------      |      | Access parent page and locate Navigator control so we can invoke the Save method
|       |                                    |----|-----
|       |                                    |      |
|       ---------------------------      |
|                                                   |
|       Navigtor.ascx                         |
|       ---------------------------      |
|       |                                    |      |
|       |                                    |----|----> Exposed as a property in default.aspx but restricts access to only features clients are allowed use
|       ---------------------------      |
--------------------------------------

Defauilt.aspx knows about its contents through the normal .NET mechanism. I use interfaces to expose nicely these controls
on the Default.aspx page as properties to anyone who wants to use them and has access to the default.aspx page.

Profile.aspx has access to Default.aspx because it is one of the controls on the page and therefore can get access to the NavigatorControl property and thus can invoke the save method.

The reason for using interfaces is that when exposing properties you want clients to only use what you allow them to, but save yourself the work of recreating a whole other control to do what NavigatorControl is already doing.

DaTribe
public interface ISave
{
   void Save();
}

public interface IDefault
{
   ISave NavigatorControl { get; }
}


// This is the page which holds the user control
public class Default : System.Web.UI.Page, IDefault
{
   public ISave NavigatorControl 
   {
      // This returns the actual usercontrol but 
      // restricts access to the interface methods
      get { return ucNavigator as ISave; } 
   }
}

// This is the usercontrol with save button
public class Navigator: System.Web.UI.UserControl, ISave
{
   public void Save()
   {
   }
}

// This is the usercontrol with grid
public class Profile: System.Web.UI.UserControl
{
    public void ButtonClick(object sender, EventArgs e)
    {
        if(Parent is IDefault)
        {
            var parent = Parent as IDefault;

            if(parent.NavigatorControl != null)
               parent.NavigatorControl.Save();

            // Do something else
        }
    }
}

Open in new window

0
 
LVL 1

Author Comment

by:nkewney
ID: 34111494
Hi DaTribe,

Thanks for your explanation

The navigator is *inside* the Profile control and I think this is where I'm getting confused.

I'm getting there, but could you clarify how it would work in this instance?

Thanks in advance.

Nick
0
 
LVL 18

Expert Comment

by:Richard Lee
ID: 34111637
Here is one solution. Much less complicated that before.

DaTribe
public class Navigator : System.Web.UI.UserControl
{
     public void Save()
     {
     }
}

// To make things really simple you could just
// reference the control directly from the page
// and call its save method
public class Profile: System.Web.UI.UserControl
{
    public void ButtonClick(object sender, EventArgs e)
    {
        ucNavigatorControl.Save();

        // Do something else
    }
}

Open in new window

0
 
LVL 18

Expert Comment

by:Richard Lee
ID: 34111658
Another solution which is slightly more complicated but more controlled.

DaTribe
public interface ISave
{
    void Save();
}

public class Navigator : System.Web.UI.UserControl, ISave
{
     public void Save()
     {
     }
}

// To make things really simple you could just
// reference the control directly from the page
// and call its save method
public class Profile: System.Web.UI.UserControl
{
    public ISave SaveControl
    {
        get { return ucNavigatorControl as ISave; }
    }

    public void ButtonClick(object sender, EventArgs e)
    {
        SaveControl.Save();

        // Do something else
    }
}

Open in new window

0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 18

Expert Comment

by:Richard Lee
ID: 34111670
Notice now that the main page is not involved since all needed actions are happening on the two user controls.

DaTribe
0
 
LVL 11

Expert Comment

by:b_levitt
ID: 34111713
I liked your original thought with a delegate/event.  I would define some sort of "SelectedItemChanged" event in your navigation control:

public class NavigatorControl() : UserControl
{
    public event EventHandler SelectedItemChanged;

    //your navigation button handler
    protected void NextItemButton_OnClick(Object sender, EventArgs e)
    {
      //Check for event registrations
      if(SelectedItemChanged != null)
      {
        //passing a reference to the user control itself here with 'this'
        //but it could be a reference to the actual item
        SelectedItemChanged(this, EventArgs.Empty);
      }
    }
}

And then wireup that event in the parent user control:

public class ParentControl : UserControl
{
  protected void Page_Init(Object sender, EventArgs e)
  {
    myNavigatorControl.SelectedItemChanged += new EventHandler(myNavigatorControl_SelectedItemChanged);
  }

  //the handler for the item changed event
  protected void myNavigatorControl_SelectedItemChanged(Object sender, EventArgs e)
  {
     //and your parent level save...
     this.Save();
  }
0
 
LVL 11

Expert Comment

by:b_levitt
ID: 34111742
By the way, this is the article that helped me years ago with events and delegates.  It does a great job with the real world boss/worker paralell that makes it really easy to follow.
http://www.codeproject.com/KB/cs/delegate_bedtime.aspx
0
 
LVL 1

Author Comment

by:nkewney
ID: 34112321
Thanks guys.

I'm going to study both solutions now and I'll let you know how I get on.
0
 
LVL 1

Author Comment

by:nkewney
ID: 34112434
Hi DaTribe,

I just wanted to confirm something with you.

Referring to your example below, am I correct in thinking that in this instance, the button click is in the "Lead Profile"

I'm trying to catch the event in the Navigator (just in case the user doesn't press save on the Profile page)

Is this correct?

Thanks again for your patience.

Nick
public class Navigator : System.Web.UI.UserControl

{

     public void Save()

     {

     }

}



// To make things really simple you could just

// reference the control directly from the page

// and call its save method

public class Profile: System.Web.UI.UserControl

{

    public void ButtonClick(object sender, EventArgs e)

    {

        ucNavigatorControl.Save();



        // Do something else

    }

}

Open in new window

0
 
LVL 18

Accepted Solution

by:
Richard Lee earned 500 total points
ID: 34154756
Apologies for the late response. I didn't realise you had come back to me - was busy off answering other questions.

Let me spell out again the scenario as I understand it and then respond to your question:

1. Profile user control
2. Navigator user control
3. Profile user control contains Navigator user control

--> Just as I was spelling this out I thought I would just code it and send it to you. Makes life easier for both of us.

See: http://www.avantprime.com/experts-exchange/avantprime.web.observer.zip

This is only a VS2008 project.

BTW: I have implemented a simple observer pattern.

DaTribe
0
 
LVL 1

Author Closing Comment

by:nkewney
ID: 34206010
Fantastic. Thank you so much.

Nick
0
 
LVL 18

Expert Comment

by:Richard Lee
ID: 34207226
Glad I could help.
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Just a quick little trick I learned recently.  Now that I'm using jQuery with abandon in my asp.net applications, I have grown tired of the following syntax:      (CODE) I suppose it just offends my sense of decency to put inline VBScript on a…
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now