MemberData Extensibility
Visual FoxPro 9.0 provides extended metadata attributes for class members. Through this new extensibility model, you now have the ability to extend the functionality of class properties, methods, and events, allowing you to create design-time enhancements such as the following:
Specify a custom property editor.
Add a property, event, or method to the new Favorites tab in the Properties window.
Control the display (capitalization) of a custom property or method in the Properties window and IntelliSense.
Extend with user-defined attributes.
MemberData Extensible Model
Extensibility is provided through MemberData which uses an XML string to specify the metadata settings for class properties and methods.
The customization you add to _MemberData is at the class and global levels. The class level always overrides the global level. At the class level, support is handled by the _MemberData Property. This property contains an XML string with the actual member metadata. As a property, it is inherited and overridden by subclasses. At the global level, MemberData is specified in special Foxcode.dbf records.
MemberData Inheritance
The inheritance structure for MemberData traverses the following path:
Class -> Container -> Global
The inheritance behavior is similar to (but not the same as) standard object-oriented programming inheritance. Visual FoxPro will first look for MemberData at the Class level along the parent hierarchy. If the particular MemberData attribute or tag is not found, then the Containership hierarchy is searched (from inner container to outer). Finally, if the search is not successful at the Container level, then MemberData is searched for at the Global level (the table specified in the _FOXCODE system variable). It is important to understand that searching occurs for a particular attribute or tag within the MemberData XML (not just the existence of MemberData itself). Therefore, it is possible to have MemberData that spans multiple locations. The following example illustrates this.
A form (Myform) containing a pageframe (Mypageframe) that has a button (Mycmd) which is inherited from _commandbutton in FFC\_base.vcx has a property called “Myprop” with MemberData associated with it. The MemberData Hierarchy for Myprop is as follows:
** Class Level - Mycmd (Myclasses.vcx)
<memberdata name="Myprop" display="MYProp" type="property"/>
** Class Level - _commandbutton (_base.vcx)
<memberdata name="Myprop" display="MYPROP" type="property"/>
** Container Level - mypageframe (myclasses.vcx)
<memberdata name="Myprop" favorites="True" display="myPRop" type="property"/>
** Container Level - myform (myclasses.vcx)
<memberdata name="Myprop" favorites="False" helpfile="Myhelp.chm" type="property"/>
** Global Level - foxcode.dbf
<memberdata name="Myprop" type="property" display="MYPROP" script="DO (_CODESENSE) WITH 'RunPropertyEditor','','MYPROP'"/>
Based on the priority of (Class -> Container -> Global), the current values for Myprop MemberData settings are as follows:
display="MYProp"
favorites="True"
script="DO (_CODESENSE) WITH 'RunPropertyEditor','','myprop'"
helpfile="myhelp.chm" (note: this is a custom user-defined attribute)
Remarks
MemberData can contain XML as defined by the MemberData XSD Schema described below.
MemberData is case-sensitive. Attributes such as Favorites must be specified as “favorites.” Values are also case-sensitive (e.g., favorites=”True”).
MemberData does not need to be set for each defined attribute or tag. If a particular requested MemberData attribute or tag is not found at the current level, other MemberData along the inheritance path is searched.
If the MemberData XML contains an Override attribute set to True, additional inheritance path searching is suspended beyond that point.
If the MemberData is not valid XML, the entire XML is ignored and the search continues along the inheritance path.
If an entry in MemberData does not contain a valid value (e.g., favorites=”123”), the entry is ignored. However, the search is also suspended (similar to having Override attribute set to True).
FOXCODE.dbf, the Global Store
FOXCODE.dbf, the global store, is a Visual FoxPro table that stores IntelliSense information. If a property or method specified in the _MEMBERDATA property cannot be found in its inheritance tree, FOXCODE.dbf is searched. Because FOXCODE.dbf is a global store, any property or method setting applies to all Visual FoxPro properties or methods unless the _MEMBERDATA property is used to override the FOXCODE.dbf settings.
Note
For events, only the favorites attribute is recognized. The favorites attribute determines if a property, event, or method appears in the Favorites tab in the Properties window.
FOXCODE.dbf MEMBERDATA Format
The following table describes the format in which MemberData information is stored in FOXCODE.dbf. Each MemberData entry requires a single record with a Type field set of "E."
Field Name |
Value |
Description |
---|---|---|
Type |
E |
|
Abbrev |
<name> |
Name of the property, event1, or method. |
Cmd |
{command} |
Script to run for the property or method. |
Tip |
|
MemberData XML string for the property or method. |
Data |
|
Contents of the script to run for a custom property editor. |
1 For events, only the favorites attribute is stored. The attribute is specified in the MemberData XML string in the Tip field.
MemberData XML Content Definition
The following table lists the reserved XML elements and attributes recognized by Visual FoxPro 9.0.
Note
You can include MemberData XML with your own custom elements and attributes which Visual FoxPro will preserve but ignore.
Element |
Attribute |
Parent |
Description |
---|---|---|---|
VFPData |
|
|
Root element denoting the metadata for a class. |
memberdata |
|
VFPData |
An element containing metadata for a specific member. A member is defined as a property or method. |
memberdata |
name |
|
Name of the member (for example, Caption or MyProperty). |
memberdata |
type |
|
Property, event, or method. |
memberdata |
display |
|
Visual representation of member. This affects the display in the Properties window as well as in IntelliSense. |
memberdata |
favorites |
|
True or False. |
memberdata |
override |
|
True or False. |
memberdata |
script |
|
Script method to execute. |
MemberData XSD Schema
The following is the MemberData XSD schema Visual FoxPro employs. Descriptions of special attributes are included in the schema.
Note
The VFP MemberData schema shown below includes two MemberData document variants: a sequence of memberdata elements supported for use with Visual FoxPro classes, and a sequence of reportdata elements supported for use in extending the Visual FoxPro Reporting System. Visual FoxPro does not use reportdata elements directly, but the parallel document design allows you to use similar mechanisms to parse both types of extensions and store them in a common global store. Like class memberdata, reporting MemberData can be used both at design time and run time. For more information, see Report XML MemberData Extensions.
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="https://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="VFPData">
<xs:complexType>
<xs:choice>
<xs:sequence>
<xs:element name="reportdata" maxOccurs="unbounded">
<xs:complexType>
<xs:attributeGroup ref="Common"/>
<xs:attributeGroup ref="ReportTemplate"/>
<xs:anyAttribute processContents="lax"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:sequence>
<xs:element name="memberdata" maxOccurs="unbounded">
<xs:complexType>
<xs:attributeGroup ref="Common"/>
<xs:attributeGroup ref="PropertySheet"/>
<xs:anyAttribute processContents="lax"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:annotation>
<xs:documentation>
You can add extension attributes as required.
</xs:documentation>
<xs:documentation>
Use the name and ref attributes of the Common attribute group to
declare that certain rows "belong" to you. Use the script attribute of
the Common attribute group for design-time scripting.
</xs:documentation>
</xs:annotation>
<xs:attributeGroup name="Common">
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="type" type="xs:string"/>
<xs:attribute name="script" type="xs:string"/>
</xs:attributeGroup>
<xs:annotation>
<xs:documentation>
The ReportTemplate-specific execute attribute is a script run at
runtime (by Listeners) whereas the Common script attribute is
potentially run by design-time tools. The declass and declasslib
attributes are looked for in the header record's template information,
not individual DataEnvironment related object records. The class and
classlib attributes in the header record are not used, and can be
leveraged for a custom helper class for report builders or listeners as
desired. Class and classlib attributes in layout objects are meant for
use in run-time and design-time templating. You can use these template
classes to build custom rendering objects at runtime or to assign
common style attributes at design-time, or both.
</xs:documentation>
</xs:annotation>
<xs:attributeGroup name="ReportTemplate">
<xs:attribute name="class" type="xs:string"/>
<xs:attribute name="classlib" type="xs:string"/>
<xs:attribute name="declass" type="xs:string"/>
<xs:attribute name="declasslib" type="xs:string"/>
<xs:attribute name="execute" type="xs:string"/>
<xs:attribute name="execwhen" type="xs:string"/>
</xs:attributeGroup>
<xs:attributeGroup name="PropertySheet">
<xs:attribute name="override" type="xs:boolean"/>
<xs:attribute name="display" type="xs:string"/>
<xs:attribute name="favorites" type="xs:boolean"/>
</xs:attributeGroup>
</xs:schema>
MemberData Example
The following is an example MemberData XML string that demonstrates the use of the reserved Visual FoxPro 9.0 XML elements and attributes. The first section adds the BorderStyle property to the Favorites tab in the Properties window and displays the property name in upper-case.
The second section creates a custom property named MyProperty that is also added to the Favorites tab in the Properties window. The script named MyPropertyScript is executed when the ellipsis button for the custom property is chosen or you double-click the property.
<?xml version="1.0" encoding="Windows-1252" standalone="yes"?>
<VFPData>
<memberdata name="borderstyle" type="property" favorites="True" display="BORDERSTYLE"override="False"/>
<memberdata name="MyProperty" type="property" display="MyProperty" favorites="True" override="False" script="MyPropertyScript"/>
</VFPData>
Custom Property Editors
You can create your own custom property editor in Visual FoxPro 9.0. Your custom property editor can be run by selecting the property in the Properties window and then choosing the ellipsis (…) button or by double-clicking the property. The ellipsis button is only displayed when a property has a custom property editor.
Visual FoxPro supports custom property editors in the following manner:
When the Properties window is opened, Visual FoxPro looks at the _MemberData property and its inheritance tree. If a value for the script attribute exists for a property and the script is valid, the ellipses button is displayed for the property.
The script is executed when the ellipsis button for the custom property is chosen or you double-click the property.
Custom and native Visual FoxPro properties can have custom property editors. For native Visual FoxPro properties, the script must return the proper data type and value for the property, otherwise an error is generated.
A custom property editor will override the native Visual FoxPro property editor (for example, the Color Picker for the ForeColor property).
Like the Visual FoxPro builder applications, a custom Property editor is responsible for setting the correct property value. A custom Property editor should use the ASELOBJ( ) Function to return a reference to the selected object or objects. Property editors should work in a similar manner as the Visual FoxPro builder applications, and should hide the Properties window if it is not docked. For more information about custom builder applications, see How to: Specify a Builder Application with Builder.dbf with Builder.dbf.
Custom Property Editor Menu Hooks
You can execute your own custom property editor when you choose the MemberData Editor… option from the Form menu, or when you right-click a property, event, or method and choose the Add to Favorites… option in the shortcut menu.
When you choose the MemberData Editor… option from the Form menu, four parameters are passed to the application specified in the _BUILDER System Variable. The following table describes the type of data passed to the parameters in the Builder application.
Parameter Number |
Description |
---|---|
1 |
Top level object (container) reference. |
2 |
"MemberData" text string. |
3 |
Numeric value, 0 for the class designer, 1 for the form designer. |
4 |
Name of the property, event, or method selected as a text string. |
For example, choosing the MemberData Editor… option from the Form menu is identical to executing the following command:
DO (_BUILDER) WITH oForm, "MemberData", 1
If no property is selected or the Properties window is closed, the last parameter will contain an empty string. If the Properties window is closed, the base object is passed as the first parameter. If multiple objects are selected, only the first one is passed as the first parameter.
When you choose the Add to Favorites… option in the shortcut menu, four parameters are passed to the application specified in the _BUILDER System Variable. The following table describes the type of data passed to the parameters in the Builder application.
Parameter |
Description |
---|---|
1 |
Top level object (container) reference. |
2 |
"MemberData" text string. |
3 |
Numeric value, 10 for the class designer, 11 for the form designer. |
4 |
Name of the property, event, or method selected as a text string. |
For example, choosing the Add to Favorites… option in the shortcut menu when the Caption property is selected in the Property window is identical to executing the following command:
DO (_BUILDER) WITH oForm, "MemberData", 11, "Caption"
Note
The Add to Favorites… option in the shortcut menu is disabled when the Properties window is open for the Visual FoxPro _SCREEN application system variable.
MemberDataEditor.app
Visual FoxPro includes a Member Data Editor application, MemberDataEditor.app, which lets you easily edit member metadata for properties, events, and method. When the Properties window is open, you can run MemberDataEditor.app by choosing the MemberData Editor… option from the Form menu.
The MemberDataEditor.app allows you to do the following:
Create MemberData for a property or method.
Specify if the MemberData is global (MemberData is written to FoxCode.dbf).
Specify if the MemberData overrides the global MemberData attributes.
Specify if default behavior is used for unspecified property or method attributes.
Add a property, event, or method to the Favorites tab in the Properties window.
Create a script (Visual FoxPro code) for a property or method.
Specify how a property or method is displayed in the Properties window, and specify display defaults.
Specify how XML elements are formatted.
For more information, see MemberData Editor.
Foxcode.dbf Script Hooks
Several new script records can be added to _FOXCODE (FoxCode.dbf) that contain special scripts (Visual FoxPro code) that are called during design time.
Note
The script records are not included in the default _FOXCODE table. You can find Visual FoxPro Menu Scripts in the Solution Samples application under New in Visual FoxPro 9.0. For more information about the application, see How to: Run Visual FoxPro Solution Samples.
_GetMemberData Script
The _GetMemberData script can be used by a custom property editor to add a _MEMBERDATA property to a container or controls when they are opened in the Form or Class designers. The _GetMemberData script is called for the following events:
When the Form or Class Designer is opened.
When a new control is added to the Form or Class Designer.
When a control is selected in the Form or Class Designer, or a container is clicked to select it.
The following table lists the fields and field values in the Foxcode.dbf record.
Field Name |
Value |
Description |
---|---|---|
Type |
E |
Indicates that the item is a property or method that has member metadata. |
Abbrev |
_GETMEMBERDATA |
Indicates this is the record for a _GetMemberData script. |
Data |
|
Script to run for the property or method. |
The _GetMemberData script is not passed any parameters.
Note
The _GetMemberData script can use the ASELOBJ( ) Function to obtain an object reference for the currently selected control or container.
MenuHit Script
The MenuHit script is called when a Visual FoxPro system menu is chosen. It can be used to override an existing Visual FoxPro dialog box with a custom dialog box.
The following table lists the fields and field values in the Foxcode.dbf record.
Field Name |
Value |
Description |
---|---|---|
Type |
S |
Indicates that the item is a script. |
Abbrev |
MENUHIT |
Indicates this is the MenuHit script record. |
Data |
|
Script (Visual FoxPro code) to run for the custom dialog box. |
The MenuHit script is passed a single parameter as an object containing the property values:
Parameter |
Description |
---|---|
UserTyped |
The internal Visual FoxPro system menu title from which the menu item was selected. The empty string is passed to this parameter if the menu is a shortcut menu. |
MenuItem |
The internal Visual FoxPro name of the chosen menu item. |
See System Menu Names for a listing of the internal Visual FoxPro system menu names.
To prevent Visual FoxPro from handling the menu, set the parameter object's ValueType property to V or L.
Note
Since _Foxcode supports a single MenuHit script record and it is possible that you may want to handle multiple menu items with your own custom scripts, it is recommended that you create a default MenuHit handler record that can call other records. The Foxcode menu scripts Solution Sample contains a recommended generic Menuhit script that you can use.
The following is an example script for the MenuHit record that you can use for looking up other records in _Foxcode whose Type field = "M", Abbrev field is name of menu and Data field contains script to execute. This is the same script installed for both MenuHit and MenuContext scripts by the Foxcode menu scripts Solution Sample.
LPARAMETERS toParameter
LOCAL lnSelect, lcCode, llReturn, lScriptHandled, lcSaveUdfParms
TRY
* First try FoxCode lookup for Type="M" records
lnSelect = SELECT()
SELECT 0
USE (_FOXCODE) AGAIN SHARE ORDER 1
IF SEEK('M' + PADR(UPPER(toParameter.MenuItem), LEN(ABBREV)))
lcCode = DATA
ENDIF
USE
SELECT (lnSelect)
IF NOT EMPTY(lcCode)
llReturn = EXECSCRIPT(lcCode, toParameter)
lScriptHandled=.T.
ENDIF
* Handle by passing to external routine as specified in Tip field
IF !lScriptHandled
lcProgram = ALLTRIM(toParameter.Tip)
IF FILE(lcProgram)
lcSaveUdfParms=SET("Udfparms")
SET UDFPARMS TO REFERENCE
DO (lcProgram) WITH toParameter,llReturn
SET UDFPARMS TO &lcSaveUdfParms
ENDIF
ENDIF
* Custom script successful so let's disable native behavior
IF llReturn
toParameter.ValueType = 'V'
ENDIF
CATCH
ENDTRY
RETURN llReturn
MenuContext Script
The MenuContext script can be used to override an existing Visual FoxPro shortcut menu with a custom shortcut menu, and is called just before a Visual FoxPro shortcut menu is displayed. A shortcut menu is displayed by right-clicking a window or object.
The following table lists the fields and field values in the Foxcode.dbf record.
Field Name |
Value |
Description |
---|---|---|
Type |
S |
Indicates that the item is a script. |
Abbrev |
MENUCONTEXT |
Indicates this is the MenuContext script record. |
Data |
|
Script (Visual FoxPro code) to run for the custom shortcut menu. |
The MenuContext script is passed a single parameter which is an object containing properties that can be referenced by the script including the following:
Parameter |
Description |
---|---|
Items |
An array of items in the shortcut menu. |
UserTyped |
Indicates additional information, if available, related to context of the shortcut menu. |
MenuItem |
An internal Visual FoxPro menu ID for the shortcut menu. |
To suppress the Visual FoxPro shortcut menu from appearing, set the parameter object's ValueType property to V or L. You can use the DEFINE MENU Command with the SHORTCUT option to create a custom shortcut menu.
Note Since _Foxcode supports a single MenuContext script record and it is possible that you may want to handle multiple shortcut menus with your own custom scripts, it is recommended that you create a default MenuContext handler record that can call other records. The Foxcode menu scripts Solution Sample contains a recommended generic MenuContext script that you can use. See the MenuHit section above for this code.