Accessing ContainerControl / EmbeddedWindowControl Type

  1. ‹ Older
  2. 3 years ago

    @Norman P your best off NOT to reach inside a container at any rate

    put methods on the container that you can call that does whatever work is needed
    then even if the guts of the cc changes (you change controls names etc you can just change the code in the exposed method and things continue working)
    treat them like black boxes - you know nothing about their innards & have to use the API they provide (which of course you also get to write)
    it will make your life simpler in the long run

    I have created methods on the container control to access but what I'm trying to say is that when I loop through the windows controls and identify an EmbeddedWindowControl how can I identify what type of container control it is (other than Instr name method) in order to call a method on it and even then I still have to manually call the actual control and method since it can't be cast to anything...right?

    So let's say I have five container controls in a window and I loop through and want to call the same method on all five of them, right now I have to use ccname1.execute(), ccname2.execute() and so on. Is there an easier way rather than hard-coding each control call?

  3. Jean-Yves P

    19 Mar 2017 Pre-Release Testers, Xojo Pro Europe (France, Besançon)

    this method will give you all the containercontrols inside a given window:

    Public Function ContainerControls(extends w as Window) as ContainerControl()
      'get a list of all the container controls in a window
      
      dim theList() as ContainerControl
      dim o as Runtime.ObjectIterator = Runtime.IterateObjects
      
      while o.MoveNext
        if o.Current isA ContainerControl and ContainerControl(o.Current).Window is w  then
          theList.Append ContainerControl(o.Current)
        end if
      wend
      return theList
      
    End Function

    but it is not very efficient as it loops throught all the objects at runtime, this can be quite long on a heavy project.
    a better way is to use the notification interface (look about it in the dev center)
    at the open event of the window, register all your containercontrols inside an array of the window, then you can call them from a window's method.

  4. Eli O

    is not verified 19 Mar 2017 Europe (Berlin, Germany)
    Dim ccs As New Dictionary()
    	
    Dim iterator As Runtime.ObjectIterator = Runtime.IterateObjects()
    Do Until Not iterator.MoveNext()
      If iterator.Current IsA ContainerControl Then
        Dim cc As ContainerControl = ContainerControl(iterator.Current)
        ccs.Value(cc.Handle) = cc
      End
    Loop
    
    For i As Integer = 0 To ControlCount - 1
      If Control(i) IsA EmbeddedWindowControl Then
        Dim handle As Integer = Control(i).Handle
        Dim cc As ContainerControl = ccs.Lookup(handle, Nil)
        If cc <> Nil Then
          // Do something with cc...
        End
      End
    Next
  5. Michel B

    19 Mar 2017 Pre-Release Testers, Xojo Pro
    Edited 3 years ago

    There is a simpler way : store references to the CC when they are instantiated. In their Open event for instance. Can be done in a dictionary or an array.

    Then you cycle through the dictionary or the array, not the window.

  6. Eli O

    is not verified 19 Mar 2017 Europe (Berlin, Germany)
    Edited 3 years ago

    It would be great if EmbeddedWindowControl had a (read-only) property AsContainerControl to return the ContainerControl instance.

  7. Okay but even with a dictionary or array of all container controls in a window how can you identify the "type" and how can you call a specific method based on that specific type? So do ccType1.Execute() and ccType2.Flush() whereby Execute is a method specific to type 1 cc and Flush is a method specific to type 2 cc. I'm guessing you can't because you can't cast a type like ccType1(cc).Execute and ccType2(cc).Flush is probably not possible so you still have to go by individual control names and method calls for each one by name.

  8. Eli O

    is not verified 19 Mar 2017 Europe (Berlin, Germany)
    Edited 3 years ago

    Once you have the container control instance you can cast it to ccType1 or ccType2.

  9. Norman P

    19 Mar 2017 Xojo Inc, Pre-Release Testers, Xojo Pro Seeking work. npalardy@great-w...
    Edited 3 years ago

    IsA

    if cc isA CC1 then
    elseif cc isa CC2 then
    end if
  10. Michel B

    19 Mar 2017 Pre-Release Testers, Xojo Pro

    @Denise A Okay but even with a dictionary or array of all container controls in a window how can you identify the "type" and how can you call a specific method based on that specific type?

    How many kinds of CC do you have ? You could have a dictionary or array for each type, or do what Norman shows above.

  11. @Eli Ott Once you have the container control instance you can cast it to ccType1 or ccType2.

    @Norman P IsA
    if cc isA CC1 then elseif cc isa CC2 then end if

    Ahh, I see. I will try all that out. Thanks.

  12. 2 years ago

    Thomas T

    10 Feb 2018 Pre-Release Testers, Xojo Pro Europe (Germany, Munich)
    Edited 2 years ago

    @Michel B There is a simpler way : store references to the CC when they are instantiated.

    The problem with this is that I cannot write generic functions accessing all controls in a Window this way, though, if the window contains ContainerControls.

    E.g, I want to write a general function that finds all editable controls in a Window and sets their Enabled property to false - it won't be able to find controls inside CCs unless I explicitly pass those CCs to the function as well. Not very clean, IMO.

    I agree with Eli that EmbeddedWindowControl should provide an accessor to the ContainerControl or provide access to the Controls inside.

  13. 2 weeks ago

    James S

    Mar 21 Pre-Release Testers, Xojo Pro

    Not to resurrect an old topic ;) But I’m going to resurrect an old topic.

    Has anyone found a way around this in the meantime? I am trying to write a generic window extension that will let me do some changing of the tab order of things as I am creating much of the interface dynamically and cannot trust the information used for that to be in the proper tab order. I wish to walk every control on the window, including ones embedded on container controls but that seems to be impossible as the EmbeddedWindowControl object is undocumented, opaque and has no .controls method or obvious other way to walk it’s control array. It cannot be cast back to a ContainerControl or anything else as far as I can tell.

    I’m going to have to write specific methods for all the affected windows that use local container control references and know what they should be which is a pain as it really should be possible to find all the controls that are currently on a window even if some of them are inside a container control.

    Walking the entire object list for the entire program is not an option in this case as it’s a large program and there are millions of objects at runtime.

  14. Norman P

    Mar 21 Pre-Release Testers, Xojo Pro outside enjoying the fresh air
    Protected Module EmbeddedWindowControlExtensions
    		Function Container(extends ctrl as EmbeddedWindowControl) As ContainerControl
    		  Dim handleToFind As Integer = ctrl.Handle
    		  
    		  If handleToFind = 0 Then
    		    Return Nil
    		  End If
    		  
    		  // ok we have the handle for this EWC 
    		  // so find the matching ContainerControl
    		  
    		  Dim iter As Runtime.ObjectIterator = Runtime.IterateObjects
    		  While iter.MoveNext
    		    If iter.Current IsA ContainerControl Then
    		      Dim tInfo As Introspection.TypeInfo = Introspection.GetType(iter.Current)
    		      Dim pInfo() As Introspection.PropertyInfo = tInfo.GetProperties
    		      For Each propInfo As Introspection.PropertyInfo In pInfo
    		        If propInfo.Name = "handle" And propInfo.Value(iter.Current) = handleToFind Then
    		          Return ContainerControl(iter.Current)
    		        End If
    		      Next
    		      
    		    End If
    		    
    		  Wend
    		  
    		  Return Nil
    		  
    		End Function
    
    End Module
  15. Richard S

    Mar 22 Pre-Release Testers, Xojo Pro

    Norman - this looks like what I need, but cant quit figure out how to use it...

    • Ive added your Module EmbeddedWindowControlExtensions to my project
    • I have a TestControl class with Super=ContainerControl with several public computed properties that can raise a ValueChanged event
    • I have a Window with a variable number of TestControls with ValueChanged event methods that call the window's Evaluate() method.
    • I want in the Evaluate() method to walk all TestControls on the window and check each their 'CurrentState' properies

    So I guess I dont know how to wire your EmbeddedWindowControlExtensions to either the Window instance or my TestControl class definition.
    Can you please point me in the right direction as to how to wire this up so I can walk all of the ContainerControls on a window access their custom propreties and/or custom methods?
    Thanks

  16. Norman P

    Mar 22 Pre-Release Testers, Xojo Pro outside enjoying the fresh air

    probably by walking all the controls on the window

    for i as integer = 0 to self.ControlCount - 1
         if control(i) isa EmbeddedWindowControl then
             dim cc as containercontrol =EmbeddedWindowControl(control(i)). Container
      
             if cc isa TestControl then
                 cc.DoSomeCustomMethod
            end if
    next

    This is a WAG ( wild a_s_s_e_d gues ) based on what little i know about your project

  17. Jean-Yves P

    Mar 22 Pre-Release Testers, Xojo Pro Europe (France, Besançon)
    Edited 2 weeks ago

    @Norman P : your method still runs through all the objects at runtime to find the CC we want in the window.
    it would be so nice to have a window.containercontrols() method, just like the window.controls() one !

  18. Norman P

    Mar 22 Pre-Release Testers, Xojo Pro outside enjoying the fresh air

    It would
    But you do whats available and possible
    There may be other ways to achieve what Richard wants - this is just one option

  19. Richard S

    Mar 22 Pre-Release Testers, Xojo Pro
    Edited 2 weeks ago

    Thanks a lot for the help Norman… only other thing I seemed to need to add apparently is to down-cast cc to a TestControl. Otherwise compiler complains "Type "ContainerControl" has no member named "SomeCustomMethod". If Im missing something here please let me know.

    Dim sResult as string
    Dim myTC  as TestControl
    
    for i as integer = 0 to self.ControlCount - 1
      if control(i) isa EmbeddedWindowControl then
        dim cc as containercontrol =EmbeddedWindowControl(control(i)). Container
        if cc isa TestControl then
          myTC = TestControl(cc)  //downcast cc to specific subtype 
          sResult = myTC.SomeCustomMethod()
        end if
      end if
    next 
  20. Norman P

    Mar 22 Pre-Release Testers, Xojo Pro outside enjoying the fresh air

    ah yeah - what I get for writing code in the forum editor :)

or Sign Up to reply!