I have three objects ObjectA has an ObjectB, ObjectB has an ObjectC. When ObjectC fires an event I need ObjectA to know about it, so this is what I've done...
public delegate void EventFiredEventHandler(); public class ObjectA { ObjectB objB; public ObjectA() { objB = new ObjectB(); objB.EventFired += new EventFiredEventHandler(objB_EventFired); } private void objB_EventFired() { //Handle the event. } } public class ObjectB { ObjectC objC; public ObjectB() { objC = new ObjectC(); objC.EventFired += new EventFiredEventHandler(objC_EventFired); objC.FireEvent(); } public event EventFiredEventHandler EventFired; protected void OnEventFired() { if(EventFired != null) { EventFired(); } } private void objC_EventFired() { //objC fired an event, bubble it up. OnEventFired(); } } public class ObjectC { public ObjectC(){} public void FireEvent() { OnEventFired(); } public event EventFiredEventHandler EventFired; protected void OnEventFired() { if(EventFired != null) { EventFired(); } } }
Is this the proper way to handle this, or is there a better way? I don't want ObjectA to know about ObjectC at all, only that it raised an event.
Event bubbling is a method of event propagation in the HTML DOM API when an event is in an element inside another element, and both elements have registered a handle to that event. It is a process that starts with the element that triggered the event and then bubbles up to the containing elements in the hierarchy.
If you want to stop the event bubbling, this can be achieved by the use of the event. stopPropagation() method. If you want to stop the event flow from event target to top element in DOM, event. stopPropagation() method stops the event to travel to the bottom to top. Stop Event Bubbling.
Event bubbling is a type of event propagation where the event first triggers on the innermost target element, and then successively triggers on the ancestors (parents) of the target element in the same nesting hierarchy till it reaches the outermost DOM element or document object (Provided the handler is initialized).
If an element A is contained within element B, and element A is clicked, the click event fires for element A and then it will bubble up and fire for element B. This occurs because technically you are clicking both elements. So basically if they click the link, the click event bubbles up to the tr element.
Another approach, is to wrap it using add/remove:
public class ObjectB { ObjectC objC; public ObjectB() { objC = new ObjectC(); } public event EventFiredEventHandler EventFired { add { this.objC.EventFired += value; } remove { this.objC.EventFired -= value; } } }
That's the way I do it. however I would recommend change your firing mechanism to this to make it thread safe
protected void OnEventFired() { var tmpEvent = EventFired; if(tmpEvent != null) { tmpEvent(); } }
This keeps it from failing if EventFired becomes null between the null check and the firing.
Also it is somewhat of a standard to follow the EventHandler pattern for your event delegates.
protected virtual void OnEventFired(EventArgs e) { var tmpEvent = EventFired; if(tmpEvent != null) { tmpEvent(this, EventArgs.e); } }
I was wrong about the threadsafe pattern, here is the full threadsafe event pattern
/// <summary> /// Delegate backing the SomeEvent event. /// </summary> SomeEventHandler someEvent; /// <summary> /// Lock for SomeEvent delegate access. /// </summary> readonly object someEventLock = new object(); /// <summary> /// Description for the event /// </summary> public event SomeEventHandler SomeEvent { add { lock (someEventLock) { someEvent += value; } } remove { lock (someEventLock) { someEvent -= value; } } } /// <summary> /// Raises the SomeEvent event /// </summary> protected virtual OnSomeEvent(EventArgs e) { SomeEventHandler handler; lock (someEventLock) { handler = someEvent; } if (handler != null) { handler (this, e); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With