Class: cCJGrid

Properties  Events  Methods    Index of Classes

Used to create basic (non-data-aware) multi-row, multi-column display and entry grids



Library: Windows Application Class Library

Package: cCJGrid.pkg


The cCJGrid class provides the basis for creating multi-row, multi-column display and entry grids.

Each column in a grid is represented by a column object. The cCJGrid uses the cCJGridColumn class for its column objects. These grid column objects, which must be created by the developer, are nested inside of the cCJGrid.

Data is stored and maintained in a datasource object. The cCJGrid uses a cCJGridDataSource class for its datasource object. The cCJGrid object creates this object automatically.

A data-aware version of a grid is provided by the cDbCJGrid subclass. The cDbCJGrid uses a cDbCJGridColumn class for its column objects and a cDbCJGridDataSource for its datasource object. A subclass of the cDbCJGrid class, cDbCJGridPromptList provides support for data-aware lookup lists.

The following provides a short introduction to grids. You should refer to Using Grids for a complete overview of the grid classes. The Class Reference will provide you with syntactical and usage information about the grid classes.

Grids and the Studio

Grids can be created visually within the Studio. To create a grid, you drag a cCJGrid, cDbCJGrid or cDbCJGridPromptList from the Class Palette and drop it onto a container (view, dialog, etc.). New columns are added by dragging column objects (cCJGridColumn, cDbCJGridColumn) onto the appropriate grid object. cDbCJGridColumns may also be also created by selecting and dragging them from the DDO Explorer. When dragged from the DDO Explorer, the grid columns are bound to data (i.e., they are assigned an Entry_Item value).

Columns are moved by dragging them to a new column position. They can be resized by dragging the header column splitter. They can be removed by dragging the column off the grid. When you click on a header, that header will be selected in Code Explorer and in the Properties Panel. Therefore, when you click on a header, you will see the properties for the column and when you click elsewhere in the grid, you will see the properties for the Grid. Those visual properties that make sense to be visually modeled are visually modeled in the Studio.

For further information, see the Visual Designer.

Working with cCJGrids

When working with grids, some of your code (properties, events, methods) is written at the grid object level and some is written at to column object level.

With simple grids, the data from the datasource is loaded in a single step, usually by sending InitializeData to the grid, passing the data as an array of tDataSourceRow items. If the grid is changed, the datasource data changes as well.

Object oCustomerGrid is a cCJGrid
    Set Size to 150 271
    Set Location to 13 11
    Set peAnchors to anAll
    Set pbReadOnly to True
    Set pbSelectionEnable to True      
    Object oCustomer_Customer_Number is a cCJGridColumn
        Set piWidth to 46
        Set psCaption to "Number"
        Set peDataType to Mask_Numeric_Window
        Set psMask to "######"

    Object oCustomer_Name is a cCJGridColumn
        Set piWidth to 231
        Set psCaption to "Customer Name"

    Object oCustomer_Status is a cCJGridColumn
        Set piWidth to 52
        Set psCaption to "Status"
        Set pbCheckbox to True
        Set psCheckboxTrue to "Y"
        Set psCheckboxFalse to "N"
    Procedure LoadData 
        tDataSourceRow[] TheData
        Boolean bFound
        Integer iRows iNum iName iStatus
        // Get the datasource indexes of the various columns
        Get piColumnId of oCustomer_Customer_Number to iNum
        Get piColumnId of oCustomer_Name to iName
        Get piColumnId of oCustomer_Status to iStatus
        // Load all data into the datasource array
        Clear Customer
        Find ge Customer by 1
        Move (Found) to bFound
        While (bFound)
            Move Customer.Customer_Number to TheData[iRows].sValue[iNum] 
            Move Customer.Name to TheData[iRows].sValue[iName] 
            Move Customer.Status  to TheData[iRows].sValue[iStatus] 
            Find gt Customer by 1
            Move (Found) to bFound
            Increment iRows
        // Initialize Grid with new data
        Send InitializeData TheData
        Send MovetoFirstRow

    Procedure Activating
        Forward Send Activating
        Send LoadData


You can then access this data by calling the datasource object's DataSource function, which returns the tDataSourceRow array.

Procedure ProcessGridData
    Handle hoDataSource
    tDataSourceRow[] TheData
    Integer iRows i

    Get phoDataSource to hoDataSource
    Get DataSource of hoDataSource to TheData
    Move (SizeOfArray(TheData)) to iRows
    For i from 0 to (iRows-1)
        Send UpdateMyDataRow TheData[i]

Data Entry

All grids are built for data entry. You are allowed to edit data, save rows, delete rows, restore changed rows, insert rows and append rows. Various properties exist which allow you to enable/disable any or all of these features. All grid editing is based around the grid's SelectedRow. If you change rows, you are changing the SelectedRow. Anytime a row changes, any changes in the SelectedRow must be committed, which means it must either be saved or restored back to its original state. The grid will check if the SelectedRow is changed. If it is changed, it must be committed (saved or cleared).

The datasource actually determines what is meant by "save". With a simple datasource, it means that the datasource's array of data is updated. With a data-aware datasource, the save is made to the external data (the database). From a grid's point of view, this is all the same. It performs the same abstract steps. It checks if a save is needed, checks if a save is allowed, allows for a save verification, performs validations on all data and attempts save the data. If this fails, you cannot leave the row.

You may not actually see any of this when you work with a simple grid. By default, there is no verification and no validations and the save is internal to the datasource. Therefore, you just make an edit and move to some other part of the grid. While you may not see it, the entire row-oriented save process does occur. The same sort of thing happens with row deletes, row inserts/appends and row clearing (undo row changes).

In addition to the automatic save of row change behavior, high-level messages exist to perform these grid change tasks. These are assigned to accelerator keys as well: Request_Save (F2), Request_Delete (Shift+F2), Request_InsertRow (Shift+F10), Request_AppendRow (Move to last row and press down arrow), Request_Clear (F5).

ReadOnly Grids

Grids can be used for non-editing purposes such as display and selection. A grid is made non-editable by setting the pbReadOnly property. You choose to support row selection by setting the pbSelectionEnable property. When grids are read only, you will often wish to disable column-level focus. This can be disabled with the pbFocusSubItems property.

Multiple-Row Selection Grids

Multiple-row selection is enabled with the pbMultipleSelection property. See that topic for details on working with multiple-row selection grids.

Display Formatting, Hidden Columns, Dynamic Columns, etc.

Numerous other grid features such as display formatting, hidden and dynamic columns, etc., are handled in each individual grid column. See the cCJGridColumn class for more information.

To change display attributes, such as font, of the entire grid, rather than conditionally changing the font of individual cells, use phoReportPaintManager.


There are a number of samples of the cCJGrid class, as well as the cDbCJGrid class, in the Grids.src program in Specialized Components workspace.