How to work with Dynamic Controls in an "array"

The documentation on Dynamic Controls is pretty abysmal. I need to add members to (or remove members from) a dynamic control set of Canvasses based on some number the user selects (NumFrames). I have a control set with a single canvas (index = 0) that I can clone, but nothing is obvious about how to get this to work.

Here’s how I would expect it to work:

n = NumFrames - 1 'The control set is base 0

'Create or remove canvases from the control set based on it's current contents:
If cvsStackingFrame.Ubound < n Then
  For i = cvsStackingFrame.Ubound To n
    cvsStackingFrame.Append(New cvsStackingFram(0)) 'Create the clone and add it to the control set
  Next i
ElseIf cvsStackingFrame.Ubound > n Then
  For i = cvsStackingFrame.Ubound DownTo n + 1
    cvsStackingFrame(i).Close 'Remove them from the top down, so that the indexing works...
  Next i
End If  

I know that control sets aren’t really “Arrays”, and cvsStackingFrame.Ubound comes back with “The item doesn’t exist”, even though the “.Ubound” part autocompletes. This should be obvious, but since I can’t find the answer in the documentation I need to ask here.

Controls sets are not arrays - at all
They can actually have “holes” in the array indexes - one huge way they vary from arrays
(ie/ you could have items with indexes 0, 1, 6, 9 )

You might also peek at Example Projects > Desktop > Controls > ControlSets (which has an example that does much of what you’re seeking to do)
Also this is outlined reasonably well in the User Guides in the User Interface pdf (pages 106 - 108)

Remember the language reference is not a “how to guide”

I realize that control sets aren’t arrays, but if you don’t want people thinking of them as such, fix the IDE so that things like “.Ubound” don’t autocomplete.

If you look at the UI Users Guide (pages 106-108) you’ll see that both Control Sets and dynamic controls are discussed, but it doesn’t talk at all about dynamic controls in a control set (which is how 90% of dynamic controls are going to be used).

It’s a bit ridiculous that people have to look through the examples, rather than reading the documentation, to learn how these thing should work.

Sorry Norm, I don’t mean to go off on you, I’ll look through the example to see if I can figure it out…

I’m not sure what this even means ?
If I create the first instance then the only difference between having that one & many new ones is there are many.
The event handlers just get different indexes when they are invoked.
The positions are different.
But beyond that its just more of the same instance.

And those few pages walk through an example of creating & adding new instances to a control set at runtime.

Not sure what else you’re seeking ?

[quote=79201:@William Koperwhats]If you look at the UI Users Guide (pages 106-108) you’ll see that both Control Sets and dynamic controls are discussed, but it doesn’t talk at all about dynamic controls in a control set (which is how 90% of dynamic controls are going to be used).
[/quote]
What do you mean? In that section, the dynamic controls being discussed are control sets. How is that not clear?

Norman and Tim, after reading through the section on Dynamic Controls much more closely I finally realized it was actually talking about a control set. It’s just that the actual code shown in the User Guide never even once touched on the “index” of each of those created push buttons. The example project code that Norm pointed me to earlier was much more useful.

It finally dawned on me that dynamic Menus (which I have been using for a while) behave completely different than dynamic Controls. I’m not sure why this is, but the inconsistency sure makes things confusing.

It waists time when you find ubound in the autocomplete for a control set.

I think what isn’t clear about control sets is that there isn’t an explicit way to keep track of and manage their indices, or even [a priori] determine how many items are in the set. Internally each item knows it’s own index, but if you want to work with them from outside the set, things become very convoluted, very quickly.

Menu items are [slightly] better. Methods like Ubound, Count, Insert, Append, etc. behave the way you think they should. But even there, the indices are not easy to determine and can get messed up.

One thing that would help to make control sets more useable was the ability to do the following:

Dim ctrl As Control
For Each ctrl in ControlSet
   If ctrl.Index = SomeValue
     'Do something with ctrl
   End If
Next ctrl
for i=0 to me.controlcount-1
   ctrl=me.control(i) ' index is to ALL controls here
   if ctrl IsA TextField then 
       TF=TextField(ctrl)
          if tf.index=somevalue and tf.name="myControl" then 
             ' do something
        end if
   end if
next i

CTRL is control
TF is textfield

expand to any other controls (labels, pushbuttons etc)

Dave, that would be fine when dealing with all controls on a form. My suggestion is a way to more efficiently deal with controls in a control set.

Control sets used to behave more like menus still do (many of the “Array” methods like I mentioned above still applied). At some point Xojo made the decision to treat them differently (I assume that they’ll do the same to menus at some point in the future), but they never thought it through completely to make sure that there were methods in place to be able to efficiently work with these “Sets” from outside the set itself.

Control Set are treated no differently today than in RealStudio … they just changed the “description”…

None of the “array” features ever applied that I’m aware of…

The above code is a variation of how I’ve done it for years

You actually don’t need to track their indexes - and if you DO then I would suggest you want subclasses or some other mechanism
THe window tracks them & maintains that list so you CAN always ask it for controls it knows

Its why, believe it or not, the IDE does not use a single control set :stuck_out_tongue:
Subclasses & dynamically added containers but no control sets

You CAN count them using a loop that counts down from Window.ControlCount-1 downto 0 and then see what name they are
Indexes are harder because they can have holes

We mostly don’t use menus that way either :stuck_out_tongue:
Subclasses are how we do things - menu arrays were actually deprecated years ago

[quote=79374:@William Koperwhats]
One thing that would help to make control sets more useable was the ability to do the following:

Dim ctrl As Control
For Each ctrl in ControlSet
   If ctrl.Index = SomeValue
     'Do something with ctrl
   End If
Next ctrl
[/code][/quote]

Some of these you can add via an extends methods for yourself currently
[code]
Function ControlSet(extends w as Window, setName as string) As Control()
  dim tmp() as Control
  for i as integer = w.ControlCount - 1 downto  0
    if w.control(i).name = setName then tmp.append w.Control(i)
  next
  
  return tmp
  
End Function
[/code]

[code]Window1.Open
  
  dim c() as Control = self.ControlSet( "cc1" )
  
  break

And you could change that method to not take a name but another instance that then goes & gets every other one with the same super & name (although if they have the same name they have to be a set)

Or something like that

If that’s the case then Xojo is a lot further behind on this than I give them credit for. I’ve been able to efficiently (and logically) work with collections of controls (or objects) in VB for over 15 years!

I’m sorry, iterating over hundreds of controls on a window asking each what type of control it is, or it’s “name”, just to do something to handful of them is horribly inefficient.

[quote=79386:@William Koperwhats]If that’s the case then Xojo is a lot further behind on this than I give them credit for. I’ve been able to efficiently (and logically) work with collections of controls (or objects) in VB for over 15 years!

I’m sorry, iterating over hundreds of controls on a window asking each what type of control it is, or it’s “name”, just to do something to handful of them is horribly inefficient.[/quote]
How about you use a ContainerControl instead?

You use an actual array instead of ContainerControls. I agree that it is horribly inefficient and not productive to have to use control sets instead of arrays.

Lets start over again…

What are you trying to do that something like

 myTextfield(13).backcolor=&cff0000

doesn’t do for you?

I use the above ( ISA) code when I am dynamically re-arranging all the controls on the screen… but if I am refering to a known control instance…I refer to it directly.

But I will agree the ability to know the COUNT (such as UBOUND would provide) is an issue

Sometimes, there are times when you need to do something in an inefficient way (whether it is a limitation on the framework or it is quicker to do things inefficiently). I would not worry to much about the control looping being very inefficient unless your project is more speed critical because you possibly have a lot of controls to handle. How many controls are you using?

[quote=79393:@Dave S]What are you trying to do that something like

myTextfield(13).backcolor=&cff0000
doesn’t do for you?[/quote]

So what if you wanted to add additional text fields to your “Set”? Or change the .BackColor on all of them? Or simply determine how many “myTextFields” you already have created. My point is that there is no way, other than iterating over every single control on your Window, determining the control’s name and/or provenance, and adding things up manually, to do these things.

The concept of object “Collections” has been around a long time, complete with Keys, automatically updated indices, .Count, .Append, .Insert, methods, etc. My point is that it’s time to apply these practices in Xojo to Controls Sets (and Menus) consistently. Right now it’s a mess.

[quote=79400:@William Koperwhats]So what if you wanted to add additional text fields to your “Set”? Or change the .BackColor on all of them? Or simply determine how many “myTextFields” you already have created. My point is that there is no way, other than iterating over every single control on your Window, determining the control’s name and/or provenance, and adding things up manually, to do these things.

The concept of object “Collections” has been around a long time, complete with Keys, automatically updated indices, .Count, .Append, .Insert, methods, etc. My point is that it’s time to apply these practices in Xojo to Controls Sets (and Menus) consistently. Right now it’s a mess.[/quote]
You should probably go and use VB.NET and MonoDevelop for your development.

Or Visual Studio if you are looking to develop for Windows-only.