Listing 3: Implementing a composite component

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Drawing;
using System.Collections.Specialized;

namespace MyControls
{
  /// <summary>
  /// Defines the orientation controls.
  /// </summary>
  public enum ControlOrientation
  {
    HORIZONTAL,VERTICAL
  }
  /// <summary>
  /// A composite version of a DateRange component.
  /// </summary>
  public class DateRangeComposite :Control,INamingContainer
  {
    // the begin and end date textboxes
    protected TextBox m_beginDateTxtBox = null;
    protected TextBox m_endDateTxtBox = null;
    // client-side validators
    protected RequiredFieldValidator m_beginDateTxtReqValidator = null;
    protected RequiredFieldValidator m_endDateTxtReqValidator = null;
    // the orientation of the control
    private ControlOrientation m_orientation =
      ControlOrientation.VERTICAL;// default orientation
    // some constants
    protected const string BEGIN_DATE = "Begin Date: ";
    protected const string END_DATE = "End Date: ";
    private const int   TABLE_CELLSPACING = 2;
    private const int   TABLE_CELLPADDING = 2;
    private const string  EMPTY_TABLE_CELL = " ";
    private const string  DATE_ERROR_MSG = "Required Field.";
    /// <summary>
    /// 
    /// </summary>
    public DateRangeComposite()
    {
    }
    /// <summary>
    /// 
    /// </summary>
    public ControlOrientation Orientation
    {
      get
      {
        return m_orientation;
      }
      set
      {
        m_orientation = value;
      }
    }
    /// <summary>
    /// 
    /// </summary>
    public string BeginDate
    {
      get
      {
        EnsureChildControls();
        return m_beginDateTxtBox.Text.Trim();
      }
      set
      {
        EnsureChildControls();
        m_beginDateTxtBox.Text=value;
      }
    }
    /// <summary>
    /// 
    /// </summary>
    public string EndDate
    {
      get
      {
        EnsureChildControls();
        return m_endDateTxtBox.Text.Trim();
      }
      set
      {
        EnsureChildControls();
        m_endDateTxtBox.Text=value;
      }
    }
    /// <summary>
    /// 
    /// </summary>
    private void InitCtrls()
    {
      m_beginDateTxtBox      = new TextBox();
      m_endDateTxtBox        = new TextBox();
      // we will use the ids below to validate the textboxes on the client-side
      m_beginDateTxtBox.ID     = "m_beginDateTxtBox";
      m_endDateTxtBox.ID       = "m_endDateTxtBox";
      m_beginDateTxtReqValidator   = new RequiredFieldValidator();
      m_endDateTxtReqValidator   = new RequiredFieldValidator();
      // set validator props
      m_beginDateTxtReqValidator.ControlToValidate = m_beginDateTxtBox.ID;
      m_endDateTxtReqValidator.ControlToValidate   = m_endDateTxtBox.ID;
      m_beginDateTxtReqValidator.Display       =
        ValidatorDisplay.Dynamic;
      m_endDateTxtReqValidator.Display       =
        ValidatorDisplay.Dynamic;
      m_beginDateTxtReqValidator.ErrorMessage    = DATE_ERROR_MSG;
      m_endDateTxtReqValidator.ErrorMessage    = DATE_ERROR_MSG;
      string now           = 
        System.DateTime.Now.ToShortDateString();
      // give the textboxes some default values...today
      m_beginDateTxtBox.Text     = now;
      m_endDateTxtBox.Text     = now;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="t"></param>
    private void SetTableProps(Table t)
    {
      if(t != null)
      {
        t.CellPadding=TABLE_CELLPADDING;
        t.CellSpacing=TABLE_CELLSPACING;
      }
    }
    /// <summary>
    /// Apply server-side validation on controls.
    /// </summary>
    /// <returns></returns>
    public bool AreCtrlsValid()
    {
      bool result = false;
      if(m_beginDateTxtBox != null && m_beginDateTxtBox.Text != null && m_beginDateTxtBox.Text.Trim().Length > 0 && 
        m_endDateTxtBox != null && m_endDateTxtBox.Text != null && m_endDateTxtBox.Text.Trim().Length > 0)
      {
        try
        {
          DateTime dt = DateTime.Parse(m_beginDateTxtBox.Text.Trim());
          dt = DateTime.Parse(m_endDateTxtBox.Text.Trim());
          result        = true;
        }
        catch(Exception)
        {
        }
      }
      return result;
    }
    /// <summary>
    /// Helper method to return an empty table cell.
    /// </summary>
    /// <returns></returns>
    private TableCell GetEmptyCell()
    {
      TableCell c = new TableCell();
      Label l = new Label();
      l.Text=EMPTY_TABLE_CELL;
      c.Controls.Add(l);
      return c;
    }
    /// <summary>
    /// Creates the component vertically.
    /// </summary>
    private void CreateVertical()
    {
      Table table = new Table();
      SetTableProps(table);
      // first row
      TableRow row   = new TableRow();
      TableCell cell = new TableCell();
      Label l = new Label();
      l.Text=BEGIN_DATE;
      cell.Controls.Add(l);
      row.Cells.Add(cell);
      cell = new TableCell();
      cell.Controls.Add(m_beginDateTxtBox);
      row.Cells.Add(cell);
      cell = new TableCell();
      cell.Controls.Add(m_beginDateTxtReqValidator);
      row.Cells.Add(cell);
      table.Rows.Add(row);// add first row to table
      row   = new TableRow();
      cell  = new TableCell();
      l = new Label();
      l.Text=END_DATE;
      cell.Controls.Add(l);
      row.Cells.Add(cell);
      cell = new TableCell();
      cell.Controls.Add(m_endDateTxtBox);
      row.Cells.Add(cell);
      cell = new TableCell();
      cell.Controls.Add(m_endDateTxtReqValidator);
      row.Cells.Add(cell);
      table.Rows.Add(row);// add second row
      Controls.Add(table);// add the table to the control collection
    }
    /// <summary>
    /// Creates the component horizontally.
    /// </summary>
    private void CreateHorizontal()
    {
      // create a 3x3 table to hold the component. 

      // Create a table control
      Table table = new Table();
      // set some properties on the table
      SetTableProps(table);
      // create first row
      TableRow row   = new TableRow();
      // first cell for first row
      TableCell cell = new TableCell();
      Label l = new Label();
      l.Text=BEGIN_DATE;
      // add the label to the first cell in the first row
      cell.Controls.Add(l);
      // add the cell to the row
      row.Cells.Add(cell);
      // add client-side validation
      cell = new TableCell();
      // add the validator to the cell
      cell.Controls.Add(m_beginDateTxtBox);
      // add textbox to the second cell of the first row
      row.Cells.Add(cell);
      // allocate space for client-side validator
      cell = new TableCell();
      cell.Controls.Add(m_beginDateTxtReqValidator);
      // add cell to row
      row.Cells.Add(cell);
      // add row to table
      table.Rows.Add(row);
      cell = new TableCell();
      l  = new Label();
      l.Text=END_DATE;
      cell.Controls.Add(l);
      row.Cells.Add(cell);
      cell = new TableCell();
      cell.Controls.Add(m_endDateTxtBox);
      row.Cells.Add(cell);
      cell = new TableCell();
      cell.Controls.Add(m_endDateTxtReqValidator);
      row.Cells.Add(cell);
      table.Rows.Add(row);
      Controls.Add(table);// add the table to the control collection
    }
    /// <summary>
    /// 
    /// </summary>
    private void CreateCtrls()
    {
      if(Orientation == ControlOrientation.VERTICAL)
      {
        CreateVertical();
      }
      else
      {
        CreateHorizontal();
      }
    }
    /// <summary>
    /// 
    /// </summary>
    protected override void CreateChildControls()
    {
      InitCtrls();
      CreateCtrls();
    }
  }

}