Application Techniques



Instantiating Bound Controls Dynamically

How to dynamically create bound controls when the data source is not known until the form is running.

About this technique

Details

Category

Java Client Techniques> General techniques for controls

Description

You'll learn about:

You can run this technique code from:

NOTE   First make sure that database is running on your localhost SilverStream Server

    Related reading

See Instantiating SilverStream form controls in the chapter on advanced form techniques in the Programmer's Guide

For more about the operations of the setDataSource DSOs used in the example, see Using a setDataSource DSO in Application Techniques

When frmInstantiateControls opens, it has no data entry fields. When the user chooses a data source, the example creates data-bound controls for the properties (columns) of the selected data source. Buttons for navigating the result set continue to work when the data source changes because they call methods of the AgcData control, not the underlying data source.

Changing the data source for an AgcData control   Top of page

The valueChanged event for cboxChooseSource handles the three choices in the list: No data, Employees, and Companies.

  private void handle_cmbxChooseSource_valueChanged(AgoPropertyChangeEvent evt) 
  { 
     String newValue = (String) evt.getNewValue(); 
   
     // Only recreate controls if user's choice is different 
     if (newValue != evt.getOldValue() ) 
     { 
        deleteOldControls(); 
         
        if (newValue.equals("No data") || newValue == null) 
           return; 
         
        if (newValue.equals("Employees") ) 
        { 
           dataSource.setDataSource("dsoRDBEmployees"); 
         } 
        else if (newValue.equals( "Companies") ) 
        { 
           dataSource.setDataSource("dsoRDBCompanies"); 
         } 
        getData(); 
        instantiateControls(); 
     } 
  } 

Notes on the code

Retrieving the data   Top of page

When the AgcData control is assigned a different data source object, you need to call invokeQuery() to retrieve data.

  public void getData() 
  { 
     // Retrieve data for the selected data source 
     try 
     { 
        String sOrderBy = ""; 
        String sQuery = ""; 
        Object[] objParms = new Object[2]; 
        objParms[0] = sOrderBy; 
        objParms[1] = sQuery; 
        dataSource.invokeQuery(objParms);    
        dataSource.gotoFirst(); 
     }  
     catch (Exception e)  
     { 
        e.printStackTrace(); 
        agDialog.showMessage("Failed to get data: \n\n"  
           + e.toString()); 
     } 
  } 

Notes on the code

Adding controls dynamically   Top of page

The instantiateControls() method creates a label and a data entry field for each of the properties of the data source. agDataMgr.bind() creates the data-binding between the field and the property. Local variables keep track of the position of the controls on the form. Embedded comments explain how the code works.

  public void instantiateControls() 
    { 
     // Instantiate controls to match the property list for  
     // the selected data source.  
     // First, set up the initial coordinates.   
       
      //Start 10 pixels below the combobox  
      Rectangle rectSource = cmbxChooseSource.getBounds(); 
      int iTopMargin = rectSource.y + rectSource.height + 10;    
       
      // Line it up on the left with the combobox 
      int iLeftMargin = rectSource.x;  
       
      // Keep them above the navigation buttons 
      int iBottomY = btnFirst.getBounds().y;   
       
      // Don't go beyond the right edge of the form. 
      int iRightMostX = this.getBounds().width - CONTROL_WIDTH; 
       
      int iCurrentY = iTopMargin; 
      int iCurrentX = iLeftMargin; 
       
      // For each property in data source, create a label  
      // and a textfield. 
      for (int i = 0; i < dataSource.getPropertyCount(); i++) 
      { 
        // Create a label using the property name and add it to  
        // the form and control array 
        AgcJLabel lblControl = new AgcJLabel(); 
        lblControl.setName("lbl" + i); 
        lblControl.setBounds(iCurrentX, iCurrentY, CONTROL_WIDTH, 
            CONTROL_HEIGHT - 4); 
        lblControl.setText( dataSource.getPropertyName(i) ); 
        // add it to the form 
        this.add(lblControl); 
        // Keep track of the created control in the array       
        dataControlsArray[i*2] = lblControl;            
        // Create a text field to display the data and add it to  
        // the form and control array 
        AgcJTextField fldControl = new AgcJTextField(); 
        fldControl.setName("fld" + dataSource.getPropertyName(i) ); 
        fldControl.setBounds(iCurrentX, iCurrentY + CONTROL_HEIGHT, 
           CONTROL_WIDTH, CONTROL_HEIGHT); 
         
        // Bind the field to the property 
        agDataMgr.bind(fldControl, "Text", "getText", "setText", 
           dataSource, dataSource.getPropertyName(i) ); 
        // add it to the form 
        this.add(fldControl); 
        // Keep track of the control in the array           
        dataControlsArray[i*2+1] = fldControl;   
        // Increment coordinates for next label and text field 
        iCurrentY += CONTROL_HEIGHT * 2;       
        // If we are down to the buttons, start a new column. 
        if ( ( iCurrentY + (CONTROL_HEIGHT * 2)) > iBottomY)  
        {  
          // back to the top 
          iCurrentY = iTopMargin; 
          // Add 10 pixels between columns of fields  
          iCurrentX = iCurrentX + CONTROL_WIDTH + 10;  
        } 
        // If we are beyond the right edge of the form, stop! 
        if (iCurrentX > iRightMostX) 
          break; 
      } 
    } 

Deleting controls   Top of page

The dataControlsArray instance variable is populated with references to all the controls created in the instantiateControls() method.

  public void deleteOldControls() 
  { 
     //  
     // Delete the objects contained in the dataControlsArray  
     // from the form; then set the entry in the array to null. 
     //    
     for (int i = 0; i < dataControlsArray.length; i++) 
     { 
        if (dataControlsArray[i] != null) 
        { 
           this.remove( dataControlsArray[i] ); 
           dataControlsArray[i] = null; 
        } 
     } 
  } 

Notes on the code






Copyright © 2000, SilverStream Software, Inc. All rights reserved.