Back

Originally published in FoxTALK May 1999


Where is that control?

Containership, we have all heard the word. “Visual FoxPro has a very good containership model.” What is containership and why do we care about it? For one thing we need to work with Visual FoxPro and therefore need to deal with the VFP containership, but there are many reasons why we should learn more about containership. Using containership to our advantage will allow us to create classes that are reusable and flexible.

Containership and OOP

The concept of containership in Object Orientation is not new.  One of the diagrams used to design OO systems is called the Whole-Part diagram.  This diagram describes objects that are composed of other objects. For example a data entry Form may contain many controls, some of those controls may be grouped together into a container of some kind, etc.

Containership requires that we address objects where they “live”.  Not unlike addressing a letter to someone, we must tell VFP where the object is that we want to manipulate.  If you want to send me a letter you cannot simply address it to Jim Booth.  The postman will never find me that way.  You need to tell the postman that I live in a country named USA, in a state named Connecticut, in a town named Prospect, on a street named Birchwood Terrace, in the house numbered 1, and my name is Jim Booth.  In VFP syntax this would be;

USA.Connecticut.Prospect.BirchwoodTerrace.One.JimBooth

We address objects in VFP the same way, with their location in space.  A textbox named Text1 that is in a form named Form1 is addressed as Form1.Text1.  Put that textbox on page1 of a PageFrame in form1 and its address becomes Form1.PageFrame1.Page1.Text1.  This is the containership addressing that VFP requires.

Think of this stuff as boxes. The form is a box that contains other things, in the form box is a PageFrame box which contains only page things, and in one of the page boxes there is a textbox thing and that is the thing we want to address.   So we tell VFP to look in the form box for a PageFrame box named pageframe1, then look in that pageframe1 box for a page box named page1 and look in that page1 box for a thing named text1.

Understanding VFP’s containership model

Visual FoxPro has a number of base classes that are, by nature, containers.  That is they can contain other objects.  Among these container classes are; Formset, Form, Container, Custom, Control, Grid, PageFrame, Page, and Column (be careful not to confuse the Container base class with the ability of an class to be a container).

These VFP base classes can be used to provide an Object Oriented design approach known as composition.  Composition is the combining of a number of objects into a single larger object. Composition can be done in one of two ways, early and late.

Early composition is the situation where the composite object is constructed and then the contained objects are given their behavior as members of the composite.  Late composition is different in that each individual class is fully defined with all of its behavior before they are combined inside the container.  Late composition is the desired design approach.

As an example, let’s consider an address block.  This composite class will be constructed of a textbox for the name, two textboxes for the street address, one each for city, state, and postal code.  All of these textboxes will be placed into a container class for grouping them together.  What’s the benefit of creating this class?  The most obvious is reuse, for each form in an application that requires an address block we just need to drop our address block object in the form and be done with it.

Now for the early versus late issue.  In early composition we would construct the container class with the textboxes in it and then write code into the various textboxes to give them their behavior. Perhaps we write code in the Valid of the State and Postal Code textboxes to validate the entry of US state and zip code information. With late composition we define the state and postal code textboxes as independent classes and then later combine them with the others in the container.

How’s one method different from the other?  You will see the difference when you want to modify the behavior of the address block.  Assume you need to now create an international address block.  With the early composition class you would subclass the address block class and then try altering the behavior of the contained objects.  This is pretty easy as long as you want all of the controls, but if you want to remove the street address textboxes and replace them with an editbox you are in for a surprise.  Visual FoxPro will not allow you to remove any of the textboxes because they are members of the parent class, so your only options are to make the textboxes invisible or to construct a new address block class.  If you choose the latter you will have to rewrite the behavior code for all of the textboxes you keep as that behavior is defined in the container and not the textbox class.

With late composition you just make a new address block class and put in it what you want.  Since you defined each textbox as its own class, you add the ones you want and leave out those that you do not want.

Coding for containership

Ok, so we see the benefits of containership and composition, but how do we deal with containership in our code? We’ve seen earlier that we need to use the containership hierarchy to address objects at runtime where they live. There is more than one way to address an object though, and some are better then others.

For example, examine the form in figure 1.

Figure 1 a form with various levels of containership.

This form has two instances of a container class with a textbox and a command button it. The first is on page 1 of the outer PageFrame (container 1), the second is on page 1 of the inner PageFrame (container 2).  The behavior of the command button is to alter the value of its sibling textbox to match the button’s caption.

One approach for this in container 2 is to write code like the following;

ThisForm.PageFrame1.Page1.PageFrame1.Page1.Container1.Text1.Value = “ABC”

Using the full containership to address the control.  However, if this code is used and container 1 is created by copying container 2 and pasting it on the other page, what behavior would we get from the button in container 1? The button in container 1 would change the textbox in container 2, because the addressing is absolute.

Instead we can use indirect referencing for the button’s code;

This.Parent.Text1.Value = “ABC”

Now both buttons will address the textbox that is sibling to them in the same container. An even better design would be to give the container a method for updating it controls and have the button call that method (a mediator pattern). Why is the mediator better, because we can now change the name of the textbox and we only need to fix code in the container, the button doesn’t care about the textbox’s name any more. Not only that, we could add more controls to the container and have the button affect all of them without altering the code in the button.

Some Definitions

In the previous section we introduced some syntax components that may be new to some of you.  Her we will provide some definitions.

Term

Definition

THIS

An object reference to the object that contains the code

THISFORM

An object reference to the form that contains the code even if that code is in a contained object.

THISFORMSET

An object reference to the formset that contains the code even if that code is in a contained object or form.

Parent

An object reference to the immediate container of the object that contains the code.  Parent can be combined to walk backwards up a containership tree, so if a textbox is contained in a page of a PageFrame in a form, This.parent.Parent.Parent refers to the form.

ActiveX and OLEControls

There have been a number of reports that the new Calendar 8.0 control does work correctly.  Folks report that when they try to set or read the calendar control’s value property they get an erroneous error condition telling them that the property doesn’t exist.

To understand the reason for the error and way to eliminate it is important to understand the containership for ActiveX controls in Visual FoxPro.  VFP uses the OLEControl to contain ActiveX controls. The calendar control is actually contained inside an OLEControl. To address this contained control you can use the Object property of the OLEControl.  This object property is a reference to the object contained inside of the OLEControl.  The following two lines of code explain what I mean here;

ThisForm.OLEControl1.Value = {^1999/01/01} && causes the error

ThisForm.OLEControl1.Object.Value = {^1999/01/01} && no error

Apparently, VFP is confused by the property name Value, because the OLEControl does not have one VFP reports an error.  Usually you only need to use the Object property when both the contained object and the OLEControl share properties with the same name.  It has been my experience that you are better off if you always use the Object property when addressing the object inside of the OLEControl.

Summary

This article only scratches the surface of the containership issues in Visual FoxPro.  The subject of containership could be covered in an entire book. We have discussed the major aspects of containership in how it affects our coding and the behavior of our systems. You have seen how to make the most of Visual FoxPro’s containership model in your work and how to avoid problems that can result from misunderstanding of the containership issue.