what is the best way to keep a child control up to date for changes in the parent.
I have a number of child controls hosted inside my parent object and I can think of two ways to send change information to them.
1) wire the child control to an event in the parent and fire that event on a change in the parent
2) keep a list of the children in an array and iterate through the array when the change has happened and invoke a method in the child to handle the new changes.
I hope I describe it okay.
Both work but there is probably a right way to handle this and a wrong way.
EDIT:
below is my code...for event method. I am not happy with how I have wired the child to the parent;any sugestions.
The Parent...
public class A_Parent
{
public delegate void DelUpdateMessage( string msg );
public event DelUpdateMessage UpdateMessage;
public A_Parent()
{
a_Child1.prnt = this;
a_Child2.prnt = this;
a_Child3.prnt = this;
a_Child4.prnt = this;
}
private void FireUpdateMessageEvent( string message)
{
var handlers = UpdateMessage;
if (handlers != null)
handlers( message );
}
}
The child...
public class A_Child
{
A_Parent pnt;
public A_Parent prnt
{
set
{
pnt = value;
pnt.UpdateMessage += new A_Parent.DelUpdateMessage(pnt_UpdateMessage);
}
}
void pnt_UpdateMessage(string msg) { }
}
Your #1 solution is the best bet, as it allows you to change around your implementation without a change in the parent. Since the parent arguably doesn't care if it has children, the event-based approach is ideal.
UPDATE
The reverse-event approach is disingenuous. People are stating that the parents clearly know what children are interested in them, and I simply tend to disagree with that statement. My designs usually have the children dynamically interested in the parent, and the children subscribing to the events is generally the most favorable way of doing so.
You can find such examples in the .NET model, such as the Page which has events that you can tie into.
Events are not the proper choice here. The parent never has a problem figuring out what child controls need to be notified. Simply add a public method to the UC, like UpdateMessage(). The parent can directly call them.
Reserve events for being able to notify listeners when you have no idea what listeners might be interested. Having a "reverse event" like you're contemplating is unhealthy, it keeps a reference on the form. A form should never be referenced so that it can get garbage collected when it closes. That isn't a real problem here, since the reference is held by a child control, but the principle holds.
Event mechanism is a common routine for such tasks. It will be much more flexible than your second solution.
Related
This question already has answers here:
Communicate between two windows forms in C#
(12 answers)
Closed 3 years ago.
Throughout my time coding in the realm of C# WinForms, I have had many instances in which I have come across different methods of passing data between forms. I work on a large codebase -- some of these methods were written by others, which I subsequently extended, and others were written by myself. It seems there are two main paradigms, both of which I have coded rather comfortably.
1.) Pass the parent form to the child when instantiating or showing the child form. For example:
ChildForm.Instance = new ChildForm(this);
--Or--
ChildForm.Instance = new ChildForm();
ChildForm.Instance.Show(this.TopLevelControl);
This allows the child to pull information from the parent, as well as allows the parent to call methods on the child. Bear with me for a moment -- I do realize that this breaks so many paradigms, and is "bad" practice -- remember, I'm encountering much of this during maintenance of a larger codebase to which I am required to make incremental adjustments without doing a complete refactoring.
2.) Use an event delegate to allow for data to be transferred between parent and child forms. To the best of my knowledge, this still requires that the parent form establish this event when spawning the child. For example:
Within parent:
childForm = new ChildForm(this);
DataRead += new DataReadEventHandler(childForm.ChildForm_DataRead);
Within child:
public void ChildForm_DataRead(Data data)
{
if (InvokeRequired)
{
Invoke(new MethodInvoker(delegate() { ChildForm_DataRead(data); }));
}
else
//do something
}
Something of this nature. Now, I'm still not a strong coder in C# WinForms, but I do realize that the event/messaging approach is probably "better" from a design perspective.
Now, here is my question.
I have a main form, for naming's sake: ParentForm. ParentForm currently utilizes the latter form (har har!) of messaging to pass data to, let's say, FirstChildForm. Essentially, once ParentForm acquires data, it triggers the DataReadEventHandler, and data is passed from ParentForm to FirstChildForm.
No problem.
Now, I /also/ have a form spawned from ParentForm, called SecondChildForm. NB: this is not another instance of ChildForm... it's an entirely different form. Here's the catch -- when data updates on SecondChildForm, I want to have this data passed to FirstChildForm. It seems like such a simple idea, although I'm having some difficulty wrapping my head around how to implement it. All I can think of is setting up unique event handlers from ParentForm for each child, and having the event handler from SecondChildFrom then trigger ParentForm's event handler for FirstChildForm... this sounds terribly convoluted, as the data (of non-trivial size, I might add), must be first passed from SecondChildForm to ParentForm, and subsequently from ParentForm to FirstChildForm.
Is there a better way of doing this?
Also, I'd really prefer not to say this, but, to be perfectly honest, in this highly closed application, I'm OK with breaking paradigm for simplicity if the proper method is highly convoluted (would nevertheless allocate time in the future for proper refactoring -- yes, I actually /am/ able to do this!).
Cheers!
-Kadaj
So the data is first generated on the second child, so on that form we'll want an event that can be triggered that can provide that data:
public class SecondChildForm : Form
{
public event Action<MyData> SomethingHappened;
//Other code, including code that fires the event at some point
}
Then we have the first child which has some method that needs to be called passing in that data:
public class FirstChildForm : Form
{
public void WhenSomethingHappens(MyData data)
{
//Do stuff with data
}
}
Finally we have the main form that creates both of the forms and wires up the appropriate event handlers:
public class ParentForm : Form
{
public ParentForm()
{
FirstChildForm firstChild = new FirstChildForm();
SecondChildForm secondChild = new SecondChildForm();
secondChild.SomethingHappened += firstChild.WhenSomethingHappens;
//show forms and do other stuff
}
}
Voila.
Note that using this pattern each child doesn't know anything about their parent. They expose information needed by the parent through events, and they allow the parent to affect it through public methods, but they don't know or care which class(es) are using them. The parent does know about it's child type; it's appropriate for it to have an instance of the specific child type and to manipulate it's public members (but not its inner controls, which shouldn't be public) directly.
In the program I am creating, I have a large amount of enums
enum kEvents
{
Start = 0,
End,
EntityCreated,
}
In this program, there is a huge list of Entities.
Each entity holds a list of "kEvents" that it is "Registered to"
Every time an object says "Call the Start event" I have to iterate through every single entity in the game, and find out if they are "listening" for that event.
Note: I know that c# has event handlers, but I was hoping to create this enum system from the ground up instead.
This being the case, what is the best way to:
Hold the collection of enums in each entity object
Check if the entity holds the triggered enum
I am wondering if Enums, being basically numbers, have a lower level, quicker way to handle this than a List<T> of objects.
Every time an object says "Call the Start event" I have to iterate through every single entity in the game, and find out if they are "listening" for that event.
You're doing it wrong! Iterating over every single object and checking if they're registered for an event is very inefficient! This is the typical Observer design pattern and there are several ways to go about this, here are a couple:
Have a single event which gets raised and has an enum parameter for event type (every subscriber gets it).
Have a dictionary of enums and corresponding events.
Here is what option 1 might look like:
delegate void OnEventDelegate(kEvents anEvent);
public class MyEventObservable
{
public event OnEventDelegate OnEvent;
}
public class MyEventObserver
{
// Constructors and all
// ...
public void OnEventReceived(kEvents anEvent)
{
switch(anEvent)
{
// switch through all the events and handle the ones that you need
}
}
}
MyEventObserver observer = new MyEventObserver();
MyEventObservable observable = new MyEventObservable();
observable.OnEvent += new OnEventDelegate(observer.OnEventReceived);
Here is option 2:
public class MyEventObservable
{
private Dictionary<kEvents, List<IObserver>> _observers;
MyEventObservable()
{
// Initialize the dictionary with all the events
}
public void RegisterObserver(kEvents event, IObserver observer)
{
_observers[event].Add(observer);
}
}
interface class IObserver
{
void Notify(kEvents anEvent);
}
public MyEventObserver: IObserver
{
// Constructors and all
// ...
// Override the IObserver
public void Notify(kEvents anEvent)
{
switch(anEvent)
{
// switch through all the events and handle the ones that you need
}
}
}
MyEventObserver observer = new MyEventObserver();
MyEventObservable observable = new MyEventObservable();
observable.RegisterObserver(kEvents.Start, observer);
Option two will reduce the number of events each observer has to handle, but it comes at the cost of having to register for every event separately (which adds coding complexity). This means that option 2 will work faster because there are fewer function calls to make. Depending on how "crazy" you want to get with the performance, there might be other options that can help you to speed it up but this should set you on the right track.
P.S. I have not compiled any of the code, but it should give you a general idea of how things ought to work.
It seems to me that you want to implement some kind of publish/subscribe scheme, some centralized event sink that the Entities can subscribe to events and provide a callback when that event happens, then other Entities would Rise the event and the event sink would call all the Entities that are subscribed to that event.... but I may have not understood the question :)
Something like:
How to access controls in other class
Every time an object says "Call the Start event" I have to iterate
through every single entity in the game, and find out if they are
"listening" for that event.
If I have correctly understood what you are doing then you are doing it backwards. the knowledge of which events an entity is listening to cannot be (only) in the event itself. There must be another data structure that holds this information.
That other data structure could be something as simple as a Map from the enum constant to a list of entities.
Before I reinvent the wheel...
This is just an EXAMPLE for describing the problem -- let's say you have a backend with collection of some data, and frontend which displays one item of the collection.
At the backend I have ItemIndex -- whenever it changes, it fires up OnScroll event.
I also have AddNewItem method, it adds new item at the end of the collection. The end of the method is calling OnNewItem event handler.
And here is the catch -- in AddNewItem I have to change ItemIndex, which fires OnScroll. One of the receivers of both (!) OnScroll and OnNewItem if frontend which displays selected item.
In such case it is called twice (not good). One solution would be altering item_index instead of ItemIndex, and this way preventing OnScroll, but I don't like it because ItemIndex does not act as black box anymore.
Is there any established pattern for sequential firing events, and sending only "important" ones (here: OnNewItem overrides OnScroll)? My idea would be to define an event scope, then instead of sending events directly, just register them for sending, and at the close of scope sort them and send the required ones.
In general -- question -- how should I deal with potential sequential event triggering. Use internals to avoid sending redundant events? Ignore the overhead? ...?
The answer seems obvious to me athough I could have easily missed something:
private bool IsAdding { get; set; }
private int item_index;
private IList m_collection;
public void AddNewItem(object item)
{
if (item == null)
{
throw new Exception("Cannot add null item."); // little bit of contracting never hurts
}
m_collection.Add(item);
IsAdding = true;
ItemIndex = collection.Count - 1; //I'm just making assumptions about this piece but it is not important how you decide what your index is to answer the question
if (OnNewItem != null)
{
OnNewItem(this, EventArgs.Empty);
}
}
public int ItemIndex
{
get { return item_index =; }
set
{
item_index = value;
if (!IsAdding && OnScroll != null) //won't double fire event thanks to IsAdding
{
OnScroll(this, EventArgs.Empty);
}
IsAdding = false; //need to reset it
}
}
One thing I would note is that you made mention of just simply altering item_index directly but that wouldn't have a blackbox behavior. Well black box is all well and good ... but that term only applies to objects interacting with this class we have been discussing.
You should feel empowered to use the internals of your class within itself. It is not good OOP to blackbox items within itself. If you are doing that then your class probably has design issues where it should be split into multiple classes.
One solution is to use a 'latch' of some form. When updating, you perform your UI actions via a helper which sets a flag saying 'hey, I'm in a special state!'. Then, when raising events, you check to see if the latch is set -- if it is, you skip raising those events.
It's basically a very simple, generalised version of what Matthew posted. Depending on the situation, setting a flag may be more than adequate.
Jeremy Miller's explanation is worth reading
You could point both events at a single function. The function can determine the sender and perform the appropriate action(s).
I have defined an Event class:
Event
and all the following classes inherit from Event:
SportEventType1 SportEventType2 SportEventType3 SportEventType4
Right now I will only have SportEvents but I don't know if in the future I'll want some other kind of events that doesn't even have anything to do with Sports.
Later, I will want to draw some graphics with info taken from Events, and the drawing logic can be a bit complex. But, for the moment, I think I shouldn't think of how the drawing will be done and I believe that maybe it'd be better if that drawing part was not put as an integral part of the Event/SportEventX class chain.
I am looking for solutions for this problem. I know I could just make Event have an instance variable(attribute, for the java crowds) pointing to something as an IDrawInterface, but that would make the Event class "assume" it will be later used for drawing. I would like to make the Event class oblivious to this if possible.
Thanks!
Your intent to keep knowledge of the drawing process outside the Event class hierarchy is good.
A common way to handle this sort of thing in an OO language is the Visitor Pattern.
If you can't actually change the Event class to add the accept(Visitor v) needed for Visitor, you might consider using a Decorator or an Adapter. Getting the accept method to vary by subclass might be painful with these though. I'll think about this a bit more and maybe add further notes tonight. For now, I've got to get to work.
Here's a more complex but pretty flexible approach. We'll define an interface
for a type that can draw some events:
interface IEventRenderer
{
// Draw the given event, if it can. Return true if the event was drawn,
// false otherwise.
bool Draw(Event event);
}
It does two things: it checks to see if it can draw a given event, and, if so,
draws it. Otherwise it bails and returns false.
For example, a class that can render Sport1Events looks like:
class Sport1EventRenderer : IEventRenderer
{
public bool Draw(Event event)
{
var sportEvent = event as Sport1Event;
// can only draw this type
if (sportEvent == null) return false;
// draw the event...
return true;
}
}
Then we'll define a registry class. It's job is to maintain a collection of
these renderers and hand off the work of drawing an event to the appropriate
one:
class EventRendererRegistry
{
public void Add(IEventRenderer renderer)
{
mRenderers.Add(renderer);
}
public void Draw(Event event)
{
foreach (var renderer in mRenderers)
{
if (renderer.Draw(event)) break;
}
}
private readonly List<IEventRenderer> mRenderers = new List<IEventRenderer>();
}
All it does is find the first renderer that can successfully draw the event.
You would then use this like:
var registry = new EventRendererRegistry();
registry.Add(new Sport1EventRenderer());
registry.Draw(someEvent);
Pros:
Event types are not coupled to any rendering code.
Renderers are not coupled to each other.
Renderers are only coupled to the events they care about. (For example a
Sport2EventRenderer would not need to be coupled to Sport1Event.)
Renders can do arbitrary logic to determine if they're appropriate. We're just
doing a type test here, but we could see if the event implements a certain
interface, has a certain property, is in a certain state, etc.
Relatively fast. No reflection beyond simple casting.
Cons:
Fairly complex.
Can fail at runtime to find a matching renderer.
Have to iterate through renderer collection each time to find a match.
One other solution might be to have an DrawbleEvent abstract class where different sportingevents can inherit from.
public abstract DrawableEvent
{
Event event;
IDrawingStrategy drawingstrategy;
public Draw()
{
drawingStrategy.Draw();
}
}
public SportingEvent1 : DrawableEvent
{
SprortingEvent1(Event event, IdrawingStrategy strategy)
{
this.event=event;
this.drawingstrategy = strategy;
}
}
The Event reference can go to the strategy or to the sprorting event depending on where it is needed.
What purpose do protected or private (non-static) events in .NET really serve?
It seems like any private or protected event is more easily handled via a virtual method. I can (somewhat) see the need for this in static events, but not for normal events.
Have you had a use case before that clearly demonstrates a need or advantage for a non-static protected or private event?
Here's a slightly bizarre but real-world scenario I implemented once. You have machine-generated and user-generated halves of a partial class. The machine-generated half contains code which wishes to inform the user-generated half when some event occurs. But the user-generated half might not care to do anything, or it might care to do rather a lot. It seems rude of the machine-generated half to require that the user-generated half implement a particular method in order to handle a message they don't have any interest in listening to.
To solve this problem, the machine-generated half could fire on a private event. If the user-generated half cares, it can subscribe the event. If not, it can ignore it.
This scenario is now addressed more elegantly by partial methods in C# 3, but that was not an option back in the day.
Seems to me that a good example of where a private event is useful is in component/control building, often you may have a component that is a composite of 1 or more other components, private events that contained components can subscribe to is a handy and easy implementation of an observer pattern.
Edit:
Let me give an example...
Say you are writing a Grid type control, and inside of this control you would most likely have a bunch of contained classes that are created dynamically Rows, Cols, headers etc for example, say you want to notify these contained classes that something they care about has happend, say a Skinning change or something like that, something that you don't necesarrily want to expose as an event to the grid users, this is where private events are handy, simply have one or 2 handlers and as you create each instance of your row or col or whatever attach the handler, as otherwise you just have to write your own observer mechanism, not hard, but why when you dont have to and you can just use multicast events.
Nested types have access to the enclosing type's private and protected events. I've used this feature to notify child controls (the nested type) of state changes in the parent control (the enclosing type) in a Silverlight application.
Sorry to drag up an old thread, but I use private events with impunity in one of my projects, and personally, I find it's a good way of solving a design issue:
Here's the abbreviated code:
public class MyClass
{
private event EventHandler _myEvent;
public ExternalObject { get; set; }
public event EventHandler MyEvent
{
add
{
if (_myEvent.GetInvocationList().Length == 0 && value != null)
ExternalObject.ExternalEvent += HandleEvent;
_myEvent+= value;
}
remove
{
_myEvent-= value;
if (_myEvent.GetInvocationList().Length == 0)
ExternalObject.ExternalEvent -= HandleEvent;
}
}
private void HandleEvent(object sender, EventArgs e)
{
_myEvent.Raise(this, EventArgs.Empty); // raises the event.
}
}
Basically, MyEvent is only ever raised in the event handler of ExternalObject.ExternalEvent, so if there's no handlers for MyEvent then I don't need to attach a handler to the external event, speeding up the code slightly by saving a stack frame.
Not only the current instance can access a private member. Other instances of the same type can too! This enables some scenarios where this access control may be useful.
I am thinking of a tree structure where all nodes inherit a certain type and a private/protected event allows to propagate leaf events to their parents. Since they are the same type, the parent can register to the child's private event. Yet any client of the tree structure cannot.
I can definitely see a use case in a directory like storage system where where each directory needs to propagate its last modified date to its parent for example.