KNOWLEDGE BASE
Log In    |    Knowledge Base    |    4D Home
Tech Tip: Efficient and maintainable List Box header method
PRODUCT: 4D | VERSION: 14.x, v15.x | PLATFORM: Mac & Win
Published On: August 26, 2016

Maintaining and updating code to manage clicks in a List Box header can become a headache and highly inefficient. What makes it that way is the practice of putting code in each List Box header object. The more columns the move object methods that have to be maintained and debugged. It is far move efficient and maintainable to manage user clicks in List Box headers from one object method.

Consider the situation where the List Box is selection based but instead of listing only the field name in the Expression property of the columns, there is the name(s) of a project method(s) with a pointer to the field passed as a parameter to the method. The purpose of this method is formulation and presentation of data within a cell in the target column. It has no ability with regards of sort order.

Since sorting is not supported in a List Box columns containing expressions, the job has to be done by code triggered by a user's click on a column header. The example code below is intended to be placed in or called from the object method of the List Box itself and calls the project method that will sort the selection presented in the list box.

If (True)
   // Name: Form1.List Box
   // Path: [projectForm]/Form1/List Box

   // Purpose: Manage user clicks on list box headers
    C_TEXT($MethodName_T)
    $MethodName_T:=Current method name
    //=========================== Declare Variables ===========================
    //local_variable_declarations
    C_LONGINT($Ndx;$SOA;$RIS;$FormEvt_L)
    C_POINTER($Self_P)
    //=========================== Initialize and Setup ===========================
    $FormEvt_L:=Form event
    $Self_P:=OBJECT Get pointer(Object current)
End if
   //=========================== Method Actions ===========================
Case of
    : ($FormEvt_L=On Header Click) | ($FormEvt_L=On After Sort))
       Case of
          : ($Self_P=(->Header1))
             sortListBoxColumn ($Self_P_P;->[Table_1]Field1;$FormEvt_L)

          : ($Self_P=(->Header2))
             sortListBoxColumn ($Self_P;->[Table_1]Field2;$FormEvt_L)

          : ($Self_P=(->Header3))
             sortListBoxColumn ($Self_P;->[Table_1]Field3;$FormEvt_L)

       End case

End case

//=========================== Clean up and Exit ===========================

// EOM


The project method below is an examle on how the selection sorting could be supported in this situation.


If (True)
   // Name: sortListBoxColumn
   // Path: sortListBoxColumn
   
   // Purpose: Sort a selection of records in the List Box
    C_TEXT($MethodName_T)
    $MethodName_T:=Current method name
    //=========================== Declare Variables ===========================
    //method_parameters_declarations
    C_POINTER($1;$HeaderVar_P;$2;$Field_P;$TempHdr_P)
    C_LONGINT($FormEvt_L;$3)
    //--------------------------------------------------------------------------
    //method_wide_constants_declarations
    //--------------------------------------------------------------------------
    //local_variable_declarations
    C_LONGINT($Ndx;$SOA;$RIS;$FormEvt_L;)
    C_TEXT($Name_T;$Unused_T)
    C_LONGINT($Unused_L;$TableNum_L)
    C_POINTER($Table_P)
   
End if

If (Count parameters>=3)
    //=========================== Initialize and Setup ===========================
    $HeaderVar_P:=$1
    $Field_P:=$2
    $FormEvt_L:=$3
   
    // Declare a process variable that will be used only for each header variable,
    // a process var is needed so that it still exists when the
    // On After Sort event fires
    //
    $Name_T:=OBJECT Get name(Object current)+"_temp"
    EXECUTE FORMULA("C_LONGINT("+$Name_T+")")
   
    // Since the var now exits in memory and it's name is a constructed name,
    // get a pointer to the var
    //
    $TempHdr_P:=Get pointer($Name_T)
   
    //=========================== Method Actions ===========================
   
    Case of
       : ($FormEvt_L=On Header Click)
          // Get a pointer to the list box source table
          //
          RESOLVE POINTER($Field_P;$Unused_T;$TableNum_L;$Unused_L)
          $Table_P:=Table($TableNum_L)
      
          // Determine which way the table is currently sorted
          // then sort in the opposite direction
          //
          If ($HeaderVar_P->=1)
             ORDER BY($Table_P->;$Field_P->;<)// Sort descending
             $TempHdr_P->:=2
      
          Else
             ORDER BY($Table_P->;$Field_P->;>)// Sort ascending
             $TempHdr_P->:=1
      
          End if
   
       : ($FormEvt_L=On After Sort)
          // Triggers the display of the sort icon in the column header
          // and set the value for the sort directon.
          //
          $HeaderVar_P->:=$TempHdr_P->
   
    End case
   
End if

//=========================== Clean up and Exit ===========================

// EOM