Click here to Skip to main content
15,886,110 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
Hello,

I have 3 user controls:

1) smallControl.
This control sends events when the user clicks on it:

C#
partial class smallControl
{
...
   public delegate void SendControlClickedNotification(Object sender);
   public event SendControlClickedNotification ControlClickedNotification;

      protected virtual void OnControlClicked()
      {
         if (ControlClickedNotification != null)
            ControlClickedNotification(this);
      }


2) arrayControl.
This control can add several smallControls to an array. When a smallControl is added, the arrayControl is being registered to the ControlClickedNotification event of the smallControl:

C#
  public class arrayControl
  {
    public void AddControl()
    {
      smallControl smallControlElement = new smallControl();

      smallControlElement .ControlClickedNotification += new SendControlClickedNotification(smallControlElement _Click);

      this.Add(smallControlElement);

    }
}



3) Container Control. This control contains 2 things:
an arrayControl, and a pictureBox.

I want the pictureBox to be registered to the events of SendControlClickedNotification (whenever a smallControl is clicked, I want the picture box to get the notification).

How can I do it?
Posted
Updated 22-Oct-12 23:27pm
v2

All your questions are reduced to a simple thing: you compose some children controls in some parent controls and want to introduce and expose some new events at the level of parent control, as the children are apparently hidden from the used of the user control.

There is nothing special in this situation. You simply need to work "by definition": add an event handler to the invocation list of some child's event; in the handler implementation, invoke the parent's event. Lets look at it on the simple example of one child and its Click event:

C#
public class ChildEventArgs : System.EventArgs {
    internal ChildEventArgs(Control child) { this.Child = child; } // don't do it public: the user only handles it
    public Child { get { return this.child; } }
    Control child;
}

public partial class MyParentControl {
    public MyParentControl() {
        child.Click += (sender, eventArgs) => {
             if (ChildClicked != null)
                 ChildClicked.Invoke(this, new ChildEventArgs(child));
        };
        //...
        Controls.AddChild(child);
    }
    public event System.EventHandler<ChildEventArgs> ChildCliked;
    SomeControlType child = new SomeControlType();
}


For an array (but it should be some collection instead, I presume), you basically do the same, but dynamically. Most likely, you need to add the handler to the invocation lists of children events when you add a child, but in this case, you will also need to remove a handler ("-="), to cover rare cases when a child is removed but still used outside of your control, can be added again, etc., so you would avoid multiple handlers. You can also develop special children control types to improve it. I'll leave all that for your home exercise. :-)

—SA
 
Share this answer
 
I want to add a side-note answer related to your first code fragment. The recommended practice is different: to use two parameters in the delegate type always: first one being System.Object, second one — of the type derived from System.EventArgs:

C#
public SmallControlEventArgs : System.EventArgs //...

// as base class/interfaces are not shown, could only be partial:
partial partial class SmallControl { // casing improved to meet (good) Microsoft naming conventions
   public event System.EventHandler<SmallControlEventArgs> ControlClickedNotification;
   //...
}


I don't want to say that you are absolutely required to do so: in such simple cases like Click one or two parameters are redundant. However, there are many cases when they are useful — please see Solution 1. If you use FxCop to validate your code, it will, be default rules, require following the pattern shown.

Please see:
http://msdn.microsoft.com/en-us/library/system.eventargs.aspx[^],
http://en.wikipedia.org/wiki/FxCop[^],
http://msdn2.microsoft.com/en-us/library/bb429476.aspx[^].

I would prefer to say, it's up to you; it's not required be syntax and general event functionality. But I personally always follow the recommended pattern, so far. :-)

—SA
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900