I am trying to make my own popupmenu.
It consists of a containercontrol which is the menu. Inside that are containercontrols which are the menu list items.
All the list items are created at runtime.
Now when the user clicks the list item, I would like it to call the parent containercontrol. Is there away to do that?
I am thinking I should use “addhandler”, but I am not sure.
[quote=347896:@Norman Palardy]Raise an event and have the parent implement the event
You can return values and everything[/quote]
Can it still be done that way if you are embedding the child containers at runtime?
Where would you implement the event if you don’t have an instance of the child container control to add a handler to?
the lazy one (but I’d argue the wrong way) is to use addhandler
the reason I’d say wrong is that the unconstrained use of addhandler can lead to hard to find memory leaks because a control doesn’t close and that keeps a layout in memory etc
IF you go this route make sure that you have a matching REMOVE handler when the control is to be removed from your layout
the second is to do a bit more work and make this more automagical
define an interface (which might be one with a single method or a bunch of methods)
have the layout that is the parent BE an implementor of that interface
make you containers to be embedded have a constructor that takes a parameter that is one of these interfaces
the constructor sets a private property on the container that is a weakref <- this is important
when you want to call a method of the parent (exposed by this interface) you
check if the weakref is nil and if so do not call the method
check if the weakref value is nil and if so do not call the method
get the weakref.value , cast it to the interface type, and call the method
while more work initially the upside is that to extend this to more exposed methods you update the interface, and implement the method on the parent and the call
no need to add more addhandlers and matching remove handlers
and because you use a weak ref you do not increase the ref count of the parent and thereby maybe cause a memory leak like you can with addhandler
dont get me wrong, used as intended, addhandler can be very useful
its the “oh just addhandler for …” everything that causes problems because it does increase the ref count of whatever holds the method and that can lead to hard to track down memory leaks
less code is not always “better” code
I’ll post a sample of what the second way looks like
edit : turns out this is the second one I’ve posted
[quote=347900:@Norman Palardy]3) make you containers to be embedded have a constructor that takes a parameter that is one of these interfaces
[/quote]
I’m on the verge of grasping this, but there is one part that I don’t quite understand; sorry Alexander, I don’t mean to take over your thread.
In testing this, I have a container named ChildContainerControl with a constructor:
Public Sub Constructor(classInterface as TestInterface)
mInterface = new WeakRef(classInterface)
End Sub
mInterface is a property of the ChildContainerControl with type WeakRef
What is don’t quite understand is how to get an instance of the interface which the ParentContainerControl is now implementing (I’ve added “TestInterface” to the project and have had ParentContainerControl implement that interface).
In ParentContainerControl’s open event I have:
[code]Sub Open() Handles Open
dim ti as TestInterface
dim child as new ChildContainerControl(ti)
child.EmbedWithin(self)
End Sub
[/code]
This issue with that code is that “ti” is nil.
How do I access the instance of the interface that the ParentContainerControl is implementing, so that I can pass it to the constructor of the ChildContainerControl?
Thank you for the detailed reply, that’s what makes these forums amazing!
This will definitely be something that I start using in the future now that I understand how it’s useful and how to implement the code. It’s a much cleaner approach than the gymnastics that I’ve been doing.
Out of curiosity, for an example like the one that Alexander had posted, is there a benefit to taking the extra steps to implement an interface rather than just storing a WeakRef to the ParentContainerControl itself and calling its methods from that?
From reading the docs, it seems that the class interface only brings real benefit when multiple classes share the same methods, but with different implementation.
How does the container get the reference to the parent ? Classes / controls should not just reach outside themselves arbitrarily.
At least with the constructor its obvious and self contained.
Interfaces help you keep things clear and help you separate concerns.
Regardless of whether you have 1, 10 or hundreds of classes that implement them.
They are really useful when you do have lots of classes that implement them but I would not say thats the only time they are useful.
Could you eliminate the interface in this case and pass the parent container itself devoid of the interface and do much the same (casting to the parent container type instead of the interface) ? Sure.
An interface just helps you plan for the future in a case like this.
[quote=347981:@Norman Palardy]Could you eliminate the interface in this case and pass the parent container itself devoid of the interface and do much the same (casting to the parent container type instead of the interface) ? Sure.
An interface just helps you plan for the future in a case like this.[/quote]
Yeah, that’s the structure that I was referring to.
I’m all for best practices though. Thanks for taking the time to walk through the benefits and implementation.