Working with Dynamic Tables

Working with tables is actually no different from any other part of the library; the principles and programming model apply to tables as they do to any other type of element. A table, however, is such a powerful and popular element that it is worth discussing.

To use a table, you create a DhTable object, add DhRow objects to that, and then add DhCell objects to the rows. The following are the rules for table usage:

While this may seem restrictive, you can easily create a simple container that emulates a gridbag with the following code:

        import com.ms.wfc.html.*;

        public class GridBag extends DhTable
        {
            int   cols;
            int   currCol;
            DhRow currRow;

            public GridBag(int cols)
            {
                this.cols = cols;
                this.currCol = cols;
            }

            public void add(DhElement e)
            {
                if( ++this.currCol >= cols )
                {
                    this.currRow = new DhRow();
                    super.add(currRow);
                    this.currCol = 0;
                }
                DhCell c = new DhCell();
                c.add(e);
                this.currRow.add( c );
            }

        }
   

To use this GridBag class, you just set the number of rows and columns (they must be the same with this implementation) and then assign elements to cells. The following is an example of the code in your DhDocument-derived class that uses this GridBag:

   protected void initForm()
   {
      GridBag myTable = new GridBag(5);
      for (int i = 0; i < 25; ++i){
         myTable.add(new DhText("" + i));
      setNewElements( new DhElement[] { myTable } );
      }
   }

One of the most powerful uses of the library is the combination of tables and Style objects. This combination enables you to create custom report generators that are powerful, professional looking, and easy to code.

Data Binding to Tables

Tables also have data binding capabilities. Using a com.ms.wfc.data.ui.DataSource object, you can bind data to your table, as shown in the following sample code.

.
.
.
import com.ms.wfc.data.*;
import com.ms.wfc.data.ui.*;
.
.
.
void private initForm( ){
   
   DhTable dataTable = new DhTable();
   dataTable.setBorder( 1 );
   dataTable.setAutoHeader( true );
   
   DataSource dataSource = new DataSource();
   dataSource.setConnectionString(“DSN=Northwind”);
   dataSource.setCommandText(“SELECT * FROM Products” );   
   
   // if you would like to use the table on the server,
   // call dataSource.getRecordset() to force the DataSource
   // to synchronously create the recordset; otherwise,
   // call dataSource.begin(), and the table will be populated
   // when the recordset is ready, asynchronously.
   if ( !getServerMode() ){
      dataSource.begin();
      dataTable.setDataSource( dataSource );
   } else
       dataTable.setDataSource( dataSource.getRecordset() );

   setNewElements( new DhElement[] { dataTable } );
}

If you know the format of the data that is going to be returned, you can also specify a template (repeater) row that the table will use to format the data that is returned. The steps to do this are as follows:

  1. Create your DhTable element:
    DhTable dataTable = new DhTable();
    
  2. Create your template row and set it into the table; you can also optionally create a header row. For each item in the template cell that you would like to receive data from the recordset, create a DataBinding for it.
    .
    .
    .
    DhRow repeaterRow = new DhRow();
    RepeaterRow.setBackColor( Color.LIGHTGRAY );
    RepeaterRow.setForeColor( Color.BLACK );
    DataBinding[] bindings = new DataBinding[3];
    DhCell  cell = new DhCell();
    DataBinding[0] = new DataBinding( cell, “text”, “ProductID” );
    repeaterRow.add( cell );
    cell = new DhCell();.
    DataBinding[1] = new DataBinding( cell, “text”, “ProductName” );
    cell = new DhCell();.
    cell.setForeColor( Color.RED );
    cell.add( new DhText( “$” ) );
    DhText price = new DhText();
    price.setFont( Font.ANSI_FIXED );
    DataBinding[2] = new DataBinding( price, “text”, “UnitPrice” );
    cell.add( price );
    repeaterRow.add( cell );
    
    // set up the table repeater row and bindings
    table.setRepeaterRow( repeaterRow );
    table.setDataBindings( bindings );
    
    // create and set the header row
    DhRow headerRow = new DhRow();
    headerRow.add( new DhCell( “ProductID” ) );
    headerRow.add( new DhCell( “Product Name” ) );
    headerRow.add( new DhCell( “Unit Price” ) );
    table.setHeaderRow( headerRow );
    
  3. Create a DataSource object, and set it to retrieve data in the format you expect.
    DataSource ds = new DataSource();
    ds.setConnectionString(“DSN=Northwind”);
    ds.setCommandText(“SELECT ProductID, ProductName, UnitPrice FROM Products WHERE UnitPrice < 10” );
  1. Set the DataSource into the DhTable object.
    table.setDataSource( ds );
    ds.begin();
    
  2. Add the DhTable to the document.
    setNewElements( new DhElement[] { table } );
    // alternately: add( table );

Your table is now populated with the data from the recordset and formatted like the template row.