Skip to content

Controls on Layouts: Who owns what?

Recently there was a question posted on the Xojo Forum about why a protected property on a control subclass could not be manipulated by an event handler in an instance event handler.

What the person had set up was a new control subclass with a custom protected property. Then they placed an instance of this subclass on a window layout and added one of the event handlers for the control. And in that event handler they were trying to alter the protected property. Everything seemed reasonable from their perspective.

To reproduce this:

1. Create a new desktop project.

2. Add a new subclass of a PushButton. Call it “MyButton”.

3. Add a new protected property to your MyButton class.

value as integer = 6

4. Drag MyButton onto the Window1 layout.

5. Add the Action event handler to the MyButton1 control now on Window1.

6. In the action event handler add this code:

me.Value = 99

7. Run the project.

Since the MyButton control event handler appears to be “part of the control”, it seems like the protected Value property should be accessible, right?

But it is not accessible. When you run the project, you get a compile error in the event handler that says:

“This property is protected. It can only be used from within its class.”

Let me explain why this happens. While the IDE shows you that the event is part of the control on the Window, it really isn’t part of the control. The event handler is not part of the class. That would mean every instance would have the exact same code to handle the event and that is most definitely not true. And the code is not part of the control since instances don’t get extra methods just by being created. (Imagine you did “new date” and all the sudden it had extra methods properties which we all know is not true)

So how are events handled for instances on a layout? They use AddHandler. The IDE actually creates a method that is then hooked up to that control’s event handler using AddHandler. But note, the method the IDE creates is not part of the control. It’s actually a method on the window that handles the event.

And since that method is not part of the control it cannot reach in and touch a protected property.

Follow these steps and you can see what’s going on.

1. Create a new desktop project.

2. Add a new class – Class1 – (not a subclass of anything).

3. Add a protected property to this class (protected value as integer = 5).

4. Add a new event definition “Action()”.

5. And we need to add a method that will raise this event eventually. This IS something the framework does for us already. So add a method, foo(), that has as it’s code:

RaiseEvent Action()

6. Add a property to Window1 – “Private instance as Class1”.

7. Add a method to Window1:

DoAction(me as Class1)

8. In this method put this code:

me.value = 99

7. In the open event of Window1 put this code:

instance = new class1
addhandler instance.Action, AddressOf self.DoAction
instance.foo()

And this almost exactly replicates how a control and its event handlers are set up. Note the event handler is not part of the control, it’s part of the Window. It cannot touch the protected property.