Admit it – this is one of those questions that, sooner or later, arise to every Xojo newcomer: How can I add new UI controls to the Window at runtime? And if you are considering this too, then the good news is that the answer is more simple than you probably expect… sitting right there on the Inspector under the Attributes tab. Yes, this is all about the Control Set!
Before we put our hands on it, let’s make some things clear about the Control Set:
- You can use this feature to dynamically create any kind of control based on the RectControl class.
- You can use Control Sets on Desktop and Web projects (although web projects cannot use Control Sets to dynamically create controls at runtime).
- You cannot create Control Sets for Container Controls.
- The Control Sets may seem like Arrays, because you will use an index to refer every instance from the same Control Set, but they are not. So, don’t think about them in that way.
- All of the instances of the Control Set will share the same Event Handlers, so you will have to use the additional index argument, passed to the Event Handler, in order to identify over which instance are you handling.
But, how can we create one of these Control Set after all? Well, we just need to put any control we want to use as a clonation template on the Window, even if it is placed outside the visible limits of the Window itself. Then, and with the control still selected, you just have to push on the attributes button (the one with the image of a gearwheel) on the Inspector, selecting the
New Control Set option from the
Member Of entry under the
Control Set Section.
Tip: If you change the name of the Control used to create a Control Set, then you will have to recreate the Control Set, so rename the template Control in the first place!
Once you have created the new Control Set, you will see that the first instance of the Control Set is assigned the index number 0; succesive instances will have their index increassed by one, both the ones you may add to the Window (not what we want to do in this case), and those created at runtime (what we want to do).
Now, probably you will want to change the
Visibility Property to
False on this first cloning template control, so it will not be visible to the users of the app no matter the resizing of the containing Window.
Once our cloning control is all set, it’s time to reveal all the code we will need in order to create new instances of the control at run time. Let’s indicate that we have used as cloning template Control a PushButton and that we have named it
btClon. Then, we just need this to create a new instance, making it visible on the Window:
Dim newInstance as PushButton = new btClon newInstance.visible = true
Remember that every UI component is based on (inherits from) the RectControl class, so you also can do this:
Dim newInstance as RectControl = new btClon PushButton(newinstance).visible = true
As you can see, the difference is that in this case you have to Cast the generic RectControl instance to the PushButton class in order for you to use and access all the PushButton methods and properties from code.
Why should you use this formula, then? Well, if you are thinking about creating several Types of UI components at runtime, then you will probably prefer to create them using a more generic RectControl variable or reference (maybe a RectControl Array containing all of your dinamically created controls).
As you may expect, the new instances created from a template will have the same properties, events and methods the template control has, with the difference that it will also inherit the clone properties values. This is why once a new instance is created we need to make it visible again and you will want to change other properties too, for example the
Caption and the
Top properties among others.
Modifying the Z axis order of the Control
We already know that every new created instance of the Control Set gets its index increased by one. What you have to know is that every new instance is above the previous one on the Z axis of the Window. I mean, if the control with the
Index set to 2 partially overlays the position of the control with the
Index 1, then the first one will overlay the second. What if you decide to have a control with a low index value above the others?
Currently there is no easy way we can dynamically change the Z order of a control to any desired value, but there is an easy way we can move any control to the foreground, so it can stay in front of all of them!
Let’s say that we have our cloned control with the
Index 1 and want to show it in the foreground, with the highest possible value in the Z axis. All we have to do is assign it to another RectControl as its
parent property value, for example the control we are using as cloning template. Once done, we will assign the Window again as the
parent property value of the control. The code could be something similar to this:
btClon(2).parent = btClon(0) btClon(2).parent = Window1 //Or Self or Me, depending where you place the code
In conclusion, as you can see, the creation of UI controls at runtime is something really easy to do in Xojo! But what if you need to dynamically add a group or layout of control at runtime? Well, in that case don’t forget about the ContainerControls!
Javier Rodriguez has been the Xojo Spanish Evangelist since 2008, he’s also a Developer, Consultant and Trainer who has be using Xojo since 1998. He manages AprendeXojo.com and is the developer behind the GuancheMOS plug-in for Xojo Developers and the Snippery app, among others.