diff options
| -rw-r--r-- | HISTORY | 1 | ||||
| -rw-r--r-- | framework/Exceptions/messages.txt | 17 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TButton.php | 28 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TCheckBox.php | 28 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TDataBoundControl.php | 41 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/THiddenField.php | 29 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TImage.php | 28 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TInlineFrame.php | 28 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TLabel.php | 28 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TLinkButton.php | 28 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TLiteral.php | 28 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TRepeater.php | 586 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TTableCell.php | 28 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TTextBox.php | 28 | ||||
| -rw-r--r-- | framework/interfaces.php | 23 | 
15 files changed, 803 insertions, 146 deletions
@@ -9,6 +9,7 @@ ENH: Ticket#519 - Update TActiveRecord implementation (Wei)  ENH: Added PRADO_CHMOD constant so that users can specify the permission of PRADO-created directories (Qiang)  ENH: Added Display property to TWebControl (Wei)  ENH: Added TUser.getState() and setState() for storing user session data (Qiang) +ENH: Added renderer feature to TRepeater (Qiang)  Version 3.1.0 alpha January 15, 2007  ==================================== diff --git a/framework/Exceptions/messages.txt b/framework/Exceptions/messages.txt index 1df4349f..1b9ab749 100644 --- a/framework/Exceptions/messages.txt +++ b/framework/Exceptions/messages.txt @@ -250,27 +250,24 @@ comparevalidator_controltocompare_invalid = TCompareValidator.ControlToCompare c  listcontrolvalidator_invalid_control	= {0}.ControlToValidate contains an invalid TListControl ID path, "{1}" is a {2}.
  repeater_template_required				= TRepeater.{0} requires a template instance implementing ITemplate interface.
 +repeater_itemtype_unknown				= Unknow repeater item type {0}.
 +repeateritemcollection_item_invalid		= TRepeaterItemCollection can only accept objects that are instance of TControl or its descendant class.
 +
  datalist_template_required				= TDataList.{0} requires a template instance implementing ITemplate interface.
 +datalistitemcollection_datalistitem_required = TDataListItemCollection can only accept TDataListItem objects.
 +
  datagrid_template_required				= TDataGrid.{0} requires a template instance implementing ITemplate interface.
  templatecolumn_template_required		= TTemplateColumn.{0} requires a template instance implementing ITemplate interface.
 -
  datagrid_currentpageindex_invalid		= TDataGrid.CurrentPageIndex must be no less than 0.
  datagrid_pagesize_invalid				= TDataGrid.PageSize must be greater than 0.
  datagrid_virtualitemcount_invalid		= TDataGrid.VirtualItemCount must be no less than 0.
 -
 +datagriditemcollection_datagriditem_required = TDataGridItemCollection can only accept TDataGridItem objects.
 +datagridcolumncollection_datagridcolumn_required = TDataGridColumnCollection can only accept TDataGridColumn objects.
  datagridpagerstyle_pagebuttoncount_invalid = TDataGridPagerStyle.PageButtonCount must be greater than 0.
  datafieldaccessor_data_invalid			= TDataFieldAccessor is trying to evaluate a field value of an invalid data. Make sure the data is an array, TMap, TList, or object that contains the specified field '{0}'.
  datafieldaccessor_datafield_invalid		= TDataFieldAccessor is trying to evaluate data value of an unknown field '{0}'.
 -repeateritemcollection_repeateritem_required = TRepeaterItemCollection can only accept TRepeaterItem objects.
 -
 -datagriditemcollection_datagriditem_required = TDataGridItemCollection can only accept TDataGridItem objects.
 -
 -datagridcolumncollection_datagridcolumn_required = TDataGridColumnCollection can only accept TDataGridColumn objects.
 -
 -datalistitemcollection_datalistitem_required = TDataListItemCollection can only accept TDataListItem objects.
 -
  tablerowcollection_tablerow_required	= TTableRowCollection can only accept TTableRow objects.
  tablecellcollection_tablerow_required	= TTableCellCollection can only accept TTableCell objects.
 diff --git a/framework/Web/UI/WebControls/TButton.php b/framework/Web/UI/WebControls/TButton.php index 0b118495..34f27ff2 100644 --- a/framework/Web/UI/WebControls/TButton.php +++ b/framework/Web/UI/WebControls/TButton.php @@ -47,7 +47,7 @@   * @package System.Web.UI.WebControls
   * @since 3.0
   */
 -class TButton extends TWebControl implements IPostBackEventHandler, IButtonControl
 +class TButton extends TWebControl implements IPostBackEventHandler, IButtonControl, IDataRenderer
  {
  	/**
  	 * @return string tag name of the button
 @@ -222,6 +222,32 @@ class TButton extends TWebControl implements IPostBackEventHandler, IButtonContr  	}
  	/**
 +	 * Returns the caption of the button.
 +	 * This method is required by {@link IDataRenderer}.
 +	 * It is the same as {@link getText()}.
 +	 * @return string caption of the button.
 +	 * @see getText
 +	 * @since 3.1.0
 +	 */
 +	public function getData()
 +	{
 +		return $this->getText();
 +	}
 +
 +	/**
 +	 * Sets the caption of the button.
 +	 * This method is required by {@link IDataRenderer}.
 +	 * It is the same as {@link setText()}.
 +	 * @param string caption of the button
 +	 * @see setText
 +	 * @since 3.1.0
 +	 */
 +	public function setData($value)
 +	{
 +		$this->setText($value);
 +	}
 +
 +	/**
  	 * @return boolean whether postback event trigger by this button will cause input validation, default is true
  	 */
  	public function getCausesValidation()
 diff --git a/framework/Web/UI/WebControls/TCheckBox.php b/framework/Web/UI/WebControls/TCheckBox.php index fefc9331..78002644 100644 --- a/framework/Web/UI/WebControls/TCheckBox.php +++ b/framework/Web/UI/WebControls/TCheckBox.php @@ -40,7 +40,7 @@   * @package System.Web.UI.WebControls
   * @since 3.0
   */
 -class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatable
 +class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatable, IDataRenderer
  {
  	/**
  	 * @return string tag name of the button
 @@ -180,6 +180,32 @@ class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatabl  	}
  	/**
 +	 * Returns the value indicating whether the checkbox is checked.
 +	 * This method is required by {@link IDataRenderer}.
 +	 * It is the same as {@link getChecked()}.
 +	 * @return boolean whether the checkbox is checked.
 +	 * @see getChecked
 +	 * @since 3.1.0
 +	 */
 +	public function getData()
 +	{
 +		return $this->getChecked();
 +	}
 +
 +	/**
 +	 * Sets the value indicating whether the checkbox is to be checked or not.
 +	 * This method is required by {@link IDataRenderer}.
 +	 * It is the same as {@link setChecked()}.
 +	 * @param boolean whether the checkbox is to be checked
 +	 * @see setChecked
 +	 * @since 3.1.0
 +	 */
 +	public function setData($value)
 +	{
 +		$this->setChecked($value);
 +	}
 +
 +	/**
  	 * @return boolean whether clicking on the checkbox will post the page.
  	 */
  	public function getAutoPostBack()
 diff --git a/framework/Web/UI/WebControls/TDataBoundControl.php b/framework/Web/UI/WebControls/TDataBoundControl.php index 6e1d1003..b043060d 100644 --- a/framework/Web/UI/WebControls/TDataBoundControl.php +++ b/framework/Web/UI/WebControls/TDataBoundControl.php @@ -542,4 +542,45 @@ class TListItemType extends TEnumerable  	const Pager='Pager';
  }
 +
 +/**
 + * IItemDataRenderer interface.
 + *
 + * IItemDataRenderer defines the interface that an item renderer
 + * needs to implement. Besides the {@link getData Data} property, a list item
 + * renderer also needs to provide {@link getItemIndex ItemIndex} and
 + * {@link getItemType ItemType} property.
 + *
 + * @author Qiang Xue <qiang.xue@gmail.com>
 + * @version $Id$
 + * @package System.Web.UI.WebControls
 + * @since 3.1.0
 + */
 +interface IItemDataRenderer extends IDataRenderer
 +{
 +	/**
 +	 * Returns a value indicating the zero-based index of the item in the corresponding data control's item collection.
 +	 * If the item is not in the collection (e.g. it is a header item), it returns -1.
 +	 * @return integer zero-based index of the item.
 +	 */
 +	public function getItemIndex();
 +
 +	/**
 +	 * Sets the zero-based index for the item.
 +	 * If the item is not in the item collection (e.g. it is a header item), -1 should be used.
 +	 * @param integer zero-based index of the item.
 +	 */
 +	public function setItemIndex($value);
 +
 +	/**
 +	 * @return TListItemType the item type.
 +	 */
 +	public function getItemType();
 +
 +	/**
 +	 * @param TListItemType the item type.
 +	 */
 +	public function setItemType($value);
 +}
 +
  ?>
\ No newline at end of file diff --git a/framework/Web/UI/WebControls/THiddenField.php b/framework/Web/UI/WebControls/THiddenField.php index f9fdd3b0..8a8a0c8a 100644 --- a/framework/Web/UI/WebControls/THiddenField.php +++ b/framework/Web/UI/WebControls/THiddenField.php @@ -23,7 +23,7 @@   * @package System.Web.UI.WebControls
   * @since 3.0
   */
 -class THiddenField extends TControl implements IPostBackDataHandler, IValidatable
 +class THiddenField extends TControl implements IPostBackDataHandler, IValidatable, IDataRenderer
  {
  	/**
  	 * @return string tag name of the hidden field.
 @@ -132,6 +132,33 @@ class THiddenField extends TControl implements IPostBackDataHandler, IValidatabl  	}
  	/**
 +	 * Returns the value of the hidden field.
 +	 * This method is required by {@link IDataRenderer}.
 +	 * It is the same as {@link getValue()}.
 +	 * @return string value of the hidden field
 +	 * @see getValue
 +	 * @since 3.1.0
 +	 */
 +	public function getData()
 +	{
 +		return $this->getValue();
 +	}
 +
 +	/**
 +	 * Sets the value of the hidden field.
 +	 * This method is required by {@link IDataRenderer}.
 +	 * It is the same as {@link setValue()}.
 +	 * @param string value of the hidden field
 +	 * @see setValue
 +	 * @since 3.1.0
 +	 */
 +	public function setData($value)
 +	{
 +		$this->setValue($value);
 +	}
 +
 +
 +	/**
  	 * @return boolean whether theming is enabled for this control. Defaults to false.
  	 */
  	public function getEnableTheming()
 diff --git a/framework/Web/UI/WebControls/TImage.php b/framework/Web/UI/WebControls/TImage.php index 00e32765..24efd064 100644 --- a/framework/Web/UI/WebControls/TImage.php +++ b/framework/Web/UI/WebControls/TImage.php @@ -25,7 +25,7 @@   * @package System.Web.UI.WebControls
   * @since 3.0
   */
 -class TImage extends TWebControl
 +class TImage extends TWebControl implements IDataRenderer
  {
  	/**
  	 * @return string tag name of image control
 @@ -115,6 +115,32 @@ class TImage extends TWebControl  	}
  	/**
 +	 * Returns the URL of the image file.
 +	 * This method is required by {@link IDataRenderer}.
 +	 * It is the same as {@link getImageUrl()}.
 +	 * @return string the URL of the image file.
 +	 * @see getImageUrl
 +	 * @since 3.1.0
 +	 */
 +	public function getData()
 +	{
 +		return $this->getImageUrl();
 +	}
 +
 +	/**
 +	 * Sets the URL of the image.
 +	 * This method is required by {@link IDataRenderer}.
 +	 * It is the same as {@link setImageUrl()}.
 +	 * @param string the URL of the image file.
 +	 * @see setImageUrl
 +	 * @since 3.1.0
 +	 */
 +	public function setData($value)
 +	{
 +		$this->setImageUrl($value);
 +	}
 +
 +	/**
  	 * @return string the URL to long description
  	 */
  	public function getDescriptionUrl()
 diff --git a/framework/Web/UI/WebControls/TInlineFrame.php b/framework/Web/UI/WebControls/TInlineFrame.php index c893f399..e0a57eca 100644 --- a/framework/Web/UI/WebControls/TInlineFrame.php +++ b/framework/Web/UI/WebControls/TInlineFrame.php @@ -31,7 +31,7 @@   * @package System.Web.UI.WebControls   * @since 3.0   */ -class TInlineFrame extends TWebControl +class TInlineFrame extends TWebControl implements IDataRenderer  {  	/**  	 * @return string tag name of the iframe. @@ -106,6 +106,32 @@ class TInlineFrame extends TWebControl  	}  	/** +	 * Returns the URL that this iframe will load content from +	 * This method is required by {@link IDataRenderer}. +	 * It is the same as {@link getFrameUrl()}. +	 * @return string the URL that this iframe will load content from +	 * @see getFrameUrl +	 * @since 3.1.0 +	 */ +	public function getData() +	{ +		return $this->getFrameUrl(); +	} + +	/** +	 * Sets the URL that this iframe will load content from. +	 * This method is required by {@link IDataRenderer}. +	 * It is the same as {@link setFrameUrl()}. +	 * @param string the URL that this iframe will load content from +	 * @see setFrameUrl +	 * @since 3.1.0 +	 */ +	public function setData($value) +	{ +		$this->setFrameUrl($value); +	} + +	/**  	 * @return TInlineFrameScrollBars the visibility and position of scroll bars in an iframe. Defaults to TInlineFrameScrollBars::Auto.  	 */  	public function getScrollBars() diff --git a/framework/Web/UI/WebControls/TLabel.php b/framework/Web/UI/WebControls/TLabel.php index 5d213529..7821580a 100644 --- a/framework/Web/UI/WebControls/TLabel.php +++ b/framework/Web/UI/WebControls/TLabel.php @@ -30,7 +30,7 @@   * @package System.Web.UI.WebControls
   * @since 3.0
   */
 -class TLabel extends TWebControl
 +class TLabel extends TWebControl implements IDataRenderer
  {
  	private $_forControl='';
 @@ -108,6 +108,32 @@ class TLabel extends TWebControl  	}
  	/**
 +	 * Returns the text value of the label.
 +	 * This method is required by {@link IDataRenderer}.
 +	 * It is the same as {@link getText()}.
 +	 * @return string the text value of the label
 +	 * @see getText
 +	 * @since 3.1.0
 +	 */
 +	public function getData()
 +	{
 +		return $this->getText();
 +	}
 +
 +	/**
 +	 * Sets the text value of the label.
 +	 * This method is required by {@link IDataRenderer}.
 +	 * It is the same as {@link setText()}.
 +	 * @param string the text value of the label
 +	 * @see setText
 +	 * @since 3.1.0
 +	 */
 +	public function setData($value)
 +	{
 +		$this->setText($value);
 +	}
 +
 +	/**
  	 * @return string the associated control ID
  	 */
  	public function getForControl()
 diff --git a/framework/Web/UI/WebControls/TLinkButton.php b/framework/Web/UI/WebControls/TLinkButton.php index ffa83d02..b193226e 100644 --- a/framework/Web/UI/WebControls/TLinkButton.php +++ b/framework/Web/UI/WebControls/TLinkButton.php @@ -54,7 +54,7 @@   * @package System.Web.UI.WebControls
   * @since 3.0
   */
 -class TLinkButton extends TWebControl implements IPostBackEventHandler, IButtonControl
 +class TLinkButton extends TWebControl implements IPostBackEventHandler, IButtonControl, IDataRenderer
  {
  	/**
  	 * @return string tag name of the button
 @@ -183,6 +183,32 @@ class TLinkButton extends TWebControl implements IPostBackEventHandler, IButtonC  	}
  	/**
 +	 * Returns the caption of the button.
 +	 * This method is required by {@link IDataRenderer}.
 +	 * It is the same as {@link getText()}.
 +	 * @return string caption of the button.
 +	 * @see getText
 +	 * @since 3.1.0
 +	 */
 +	public function getData()
 +	{
 +		return $this->getText();
 +	}
 +
 +	/**
 +	 * Sets the caption of the button.
 +	 * This method is required by {@link IDataRenderer}.
 +	 * It is the same as {@link setText()}.
 +	 * @param string caption of the button
 +	 * @see setText
 +	 * @since 3.1.0
 +	 */
 +	public function setData($value)
 +	{
 +		$this->setText($value);
 +	}
 +
 +	/**
  	 * @return string the command name associated with the {@link onCommand OnCommand} event.
  	 */
  	public function getCommandName()
 diff --git a/framework/Web/UI/WebControls/TLiteral.php b/framework/Web/UI/WebControls/TLiteral.php index 02061304..3ebb4039 100644 --- a/framework/Web/UI/WebControls/TLiteral.php +++ b/framework/Web/UI/WebControls/TLiteral.php @@ -31,7 +31,7 @@   * @package System.Web.UI.WebControls
   * @since 3.0
   */
 -class TLiteral extends TControl
 +class TLiteral extends TControl implements IDataRenderer
  {
  	/**
  	 * @return string the static text of the TLiteral
 @@ -51,6 +51,32 @@ class TLiteral extends TControl  	}
  	/**
 +	 * Returns the static text of the TLiteral.
 +	 * This method is required by {@link IDataRenderer}.
 +	 * It is the same as {@link getText()}.
 +	 * @return string the static text of the TLiteral
 +	 * @see getText
 +	 * @since 3.1.0
 +	 */
 +	public function getData()
 +	{
 +		return $this->getText();
 +	}
 +
 +	/**
 +	 * Sets the static text of the TLiteral.
 +	 * This method is required by {@link IDataRenderer}.
 +	 * It is the same as {@link setText()}.
 +	 * @param string the static text of the TLiteral
 +	 * @see setText
 +	 * @since 3.1.0
 +	 */
 +	public function setData($value)
 +	{
 +		$this->setText($value);
 +	}
 +
 +	/**
  	 * @return boolean whether the rendered text should be HTML-encoded. Defaults to false.
  	 */
  	public function getEncode()
 diff --git a/framework/Web/UI/WebControls/TRepeater.php b/framework/Web/UI/WebControls/TRepeater.php index 046e0a88..f6093667 100644 --- a/framework/Web/UI/WebControls/TRepeater.php +++ b/framework/Web/UI/WebControls/TRepeater.php @@ -17,52 +17,74 @@ Prado::using('System.Web.UI.WebControls.TDataBoundControl');  Prado::using('System.Util.TDataFieldAccessor');
  /**
 - * TRepeater class
 + * TRepeater class.
   *
 - * TRepeater displays its content defined in templates repeatedly based on
 - * the given data specified by the {@link setDataSource DataSource} or
 - * {@link setDataSourceID DataSourceID} property. The templates can contain
 - * static text, controls and special tags.
 + * TRepeater displays its content repeatedly based on the data fetched from
 + * {@link setDataSource DataSource}.
 + * The repeated contents in TRepeater are called items, which are controls and
 + * can be accessed through {@link getItems Items}. When {@link dataBind()} is invoked,
 + * TRepeater creates an item for each row of data and binds the data row to the item.
 + * Optionally, a repeater can have a header, a footer and/or separators between items.
   *
 - * The {@link setHeaderTemplate HeaderTemplate} property specifies the content
 - * template that will be displayed at the beginning, while
 - * {@link setFooterTemplate FooterTemplate} at the end.
 - * If present, these two templates will only be rendered when the repeater is
 - * given non-empty data. In this case, for each data item the content defined
 - * by {@link setItemTemplate ItemTemplate} will be generated and displayed once.
 - * If {@link setAlternatingItemTemplate AlternatingItemTemplate} is not empty,
 - * then the corresponding content will be displayed alternatively with that
 - * in {@link setItemTemplate ItemTemplate}. The content in
 - * {@link setSeparatorTemplate SeparatorTemplate}, if not empty, will be
 - * displayed between items.
 + * The layout of the repeated contents are specified by inline templates.
 + * Repeater items, header, footer, etc. are being instantiated with the corresponding
 + * templates when data is being bound to the repeater.
   *
 - * Each repeater item has a {@link TRepeaterItem::getItemType type}
 - * which tells the position of the item in the repeater. An item in the header
 - * of the repeater is of type TListItemType::Header. A body item may be of either
 - * TListItemType::Item or TListItemType::AlternatingItem, depending whether the item
 - * index is odd or even.
 + * Since v3.1.0, the layout can also be by renderers. A renderer is a control class
 + * that can be instantiated as repeater items, header, etc. A renderer can thus be viewed
 + * as an external template (in fact, it can also be non-templated controls).
   *
 - * You can retrive the repeated contents by the {@link getItems Items} property.
 - * The header and footer items can be accessed by {@link getHeader Header}
 - * and {@link getFooter Footer} properties, respectively.
 + * A renderer can be any control class.
 + * -If the class implements {@link IDataRenderer}, the <b>Data</b>
 + * property will be set as the data row during databinding. Many PRADO controls
 + * implement this interface, such as {@link TLabel}, {@link TTextBox}, etc.
 + * - If the class implements {@link IItemDataRenderer}, the <b>ItemIndex</b> property will be set
 + * as the zero-based index of the item in the repeater item collection, and
 + * the <b>ItemType</b> property as the item's type (such as TListItemType::Item).
 + * {@link TRepeaterItemRenderer} may be used as the convenient base class which
 + * already implements {@link IDataItemRenderer}.
   *
 - * When TRepeater creates an item, it will raise an {@link onItemCreated OnItemCreated}
 - * so that you may customize the newly created item.
 - * When databinding is performed by TRepeater, for each item once it has finished
 - * databinding, an {@link onItemDataBound OnItemDataBound} event will be raised.
 + * The following properties are used to specify different types of template and renderer
 + * for a repeater:
 + * - {@link setItemTemplate ItemTemplate}, {@link setItemRenderer ItemRenderer}:
 + * for each repeated row of data
 + * - {@link setAlternatingItemTemplate AlternatingItemTemplate}, {@link setAlternatingItemRenderer AlternatingItemRenderer}:
 + * for each alternating row of data. If not set, {@link setItemTemplate ItemTemplate} or {@link setItemRenderer ItemRenderer}
 + * will be used instead.
 + * - {@link setHeaderTemplate HeaderTemplate}, {@link setHeaderRenderer HeaderRenderer}:
 + * for the repeater header.
 + * - {@link setFooterTemplate FooterTemplate}, {@link setFooterRenderer FooterRenderer}:
 + * for the repeater footer.
 + * - {@link setSeparatorTemplate SeparatorTemplate}, {@link setSeparatorRenderer SeparatorRenderer}:
 + * for content to be displayed between items.
 + * - {@link setEmptyTemplate EmptyTemplate}, {@link setEmptyRenderer EmptyRenderer}:
 + * used when data bound to the repeater is empty.
 + *
 + * If a content type is defined with both a template and a renderer, the latter takes precedence.
 + *
 + * When {@link dataBind()} is being called, TRepeater undergoes the following lifecycles for each row of data:
 + * - create item based on templates or renderers
 + * - set the row of data to the item
 + * - raise {@link onItemCreated OnItemCreated}:
 + * - add the item as a child control
 + * - call dataBind() of the item
 + * - raise {@link onItemDataBound OnItemDataBound}:
   *
   * TRepeater raises an {@link onItemCommand OnItemCommand} whenever a button control
   * within some repeater item raises a <b>OnCommand</b> event. Therefore,
   * you can handle all sorts of <b>OnCommand</b> event in a central place by
   * writing an event handler for {@link onItemCommand OnItemCommand}.
   *
 - * Note, the data bound to the repeater are reset to null after databinding.
 - * There are several ways to access the data associated with a repeater item:
 - * - Access the data in {@link onItemDataBound OnItemDataBound} event
 + * When a page containing a repeater is post back, the repeater will restore automatically
 + * all its contents, including items, header, footer and separators.
 + * However, the data row associated with each item will not be recovered and become null.
 + * To access the data, use one of the following ways:
   * - Use {@link getDataKeys DataKeys} to obtain the data key associated with
   * the specified repeater item and use the key to fetch the corresponding data
   * from some persistent storage such as DB.
 - * - Save the data in viewstate and get it back during postbacks.
 + * - Save the whole dataset in viewstate, which will restore the dataset automatically upon postback.
 + * Be aware though, if the size of your dataset is big, your page size will become big. Some
 + * complex data may also have serializing problem if saved in viewstate.
   *
   * @author Qiang Xue <qiang.xue@gmail.com>
   * @version $Id$
 @@ -110,14 +132,148 @@ class TRepeater extends TDataBoundControl implements INamingContainer  	 */
  	private $_items=null;
  	/**
 -	 * @var TRepeaterItem header item
 +	 * @var TControl header item
  	 */
  	private $_header=null;
  	/**
 -	 * @var TRepeaterItem footer item
 +	 * @var TControl footer item
  	 */
  	private $_footer=null;
 +
 +	/**
 +	 * @return string the class name for repeater items. Defaults to empty, meaning not set.
 +	 */
 +	public function getItemRenderer()
 +	{
 +		return $this->getViewState('ItemRenderer','');
 +	}
 +
 +	/**
 +	 * Sets the item renderer class.
 +	 *
 +	 * If not empty, the class will be used to instantiate as repeater items.
 +	 * This property takes precedence over {@link getItemTemplate ItemTemplate}.
 +	 *
 +	 * @param string the renderer class name in namespace format.
 +	 * @see setItemTemplate
 +	 */
 +	public function setItemRenderer($value)
 +	{
 +		$this->setViewState('ItemRenderer',$value,'');
 +	}
 +
 +	/**
 +	 * @return string the class name for alternative repeater items. Defaults to empty, meaning not set.
 +	 */
 +	public function getAlternatingItemRenderer()
 +	{
 +		return $this->getViewState('AlternatingItemRenderer','');
 +	}
 +
 +	/**
 +	 * Sets the alternative item renderer class.
 +	 *
 +	 * If not empty, the class will be used to instantiate as alternative repeater items.
 +	 * This property takes precedence over {@link getAlternatingItemTemplate AlternatingItemTemplate}.
 +	 *
 +	 * @param string the renderer class name in namespace format.
 +	 * @see setAlternatingItemTemplate
 +	 */
 +	public function setAlternatingItemRenderer($value)
 +	{
 +		$this->setViewState('AlternatingItemRenderer',$value,'');
 +	}
 +
 +	/**
 +	 * @return string the class name for repeater item separators. Defaults to empty, meaning not set.
 +	 */
 +	public function getSeparatorRenderer()
 +	{
 +		return $this->getViewState('SeparatorRenderer','');
 +	}
 +
 +	/**
 +	 * Sets the repeater item separator renderer class.
 +	 *
 +	 * If not empty, the class will be used to instantiate as repeater item separators.
 +	 * This property takes precedence over {@link getSeparatorTemplate SeparatorTemplate}.
 +	 *
 +	 * @param string the renderer class name in namespace format.
 +	 * @see setSeparatorTemplate
 +	 */
 +	public function setSeparatorRenderer($value)
 +	{
 +		$this->setViewState('SeparatorRenderer',$value,'');
 +	}
 +
 +	/**
 +	 * @return string the class name for repeater header item. Defaults to empty, meaning not set.
 +	 */
 +	public function getHeaderRenderer()
 +	{
 +		return $this->getViewState('HeaderRenderer','');
 +	}
 +
 +	/**
 +	 * Sets the repeater header renderer class.
 +	 *
 +	 * If not empty, the class will be used to instantiate as repeater header item.
 +	 * This property takes precedence over {@link getHeaderTemplate HeaderTemplate}.
 +	 *
 +	 * @param string the renderer class name in namespace format.
 +	 * @see setHeaderTemplate
 +	 */
 +	public function setHeaderRenderer($value)
 +	{
 +		$this->setViewState('HeaderRenderer',$value,'');
 +	}
 +
 +	/**
 +	 * @return string the class name for repeater footer item. Defaults to empty, meaning not set.
 +	 */
 +	public function getFooterRenderer()
 +	{
 +		return $this->getViewState('FooterRenderer','');
 +	}
 +
 +	/**
 +	 * Sets the repeater footer renderer class.
 +	 *
 +	 * If not empty, the class will be used to instantiate as repeater footer item.
 +	 * This property takes precedence over {@link getFooterTemplate FooterTemplate}.
 +	 *
 +	 * @param string the renderer class name in namespace format.
 +	 * @see setFooterTemplate
 +	 */
 +	public function setFooterRenderer($value)
 +	{
 +		$this->setViewState('FooterRenderer',$value,'');
 +	}
 +
 +	/**
 +	 * @return string the class name for empty repeater item. Defaults to empty, meaning not set.
 +	 */
 +	public function getEmptyRenderer()
 +	{
 +		return $this->getViewState('EmptyRenderer','');
 +	}
 +
 +	/**
 +	 * Sets the repeater empty renderer class.
 +	 *
 +	 * The empty renderer is created as the child of the repeater
 +	 * if data bound to the repeater is empty.
 +	 * This property takes precedence over {@link getEmptyTemplate EmptyTemplate}.
 +	 *
 +	 * @param string the renderer class name in namespace format.
 +	 * @see setEmptyTemplate
 +	 */
 +	public function setEmptyRenderer($value)
 +	{
 +		$this->setViewState('EmptyRenderer',$value,'');
 +	}
 +
  	/**
  	 * @return ITemplate the template for repeater items
  	 */
 @@ -239,7 +395,7 @@ class TRepeater extends TDataBoundControl implements INamingContainer  	}
  	/**
 -	 * @return TRepeaterItem the header item
 +	 * @return TControl the header item
  	 */
  	public function getHeader()
  	{
 @@ -247,7 +403,7 @@ class TRepeater extends TDataBoundControl implements INamingContainer  	}
  	/**
 -	 * @return TRepeaterItem the footer item
 +	 * @return TControl the footer item
  	 */
  	public function getFooter()
  	{
 @@ -255,7 +411,7 @@ class TRepeater extends TDataBoundControl implements INamingContainer  	}
  	/**
 -	 * @return TRepeaterItemCollection list of {@link TRepeaterItem} controls
 +	 * @return TRepeaterItemCollection list of repeater item controls
  	 */
  	public function getItems()
  	{
 @@ -294,66 +450,117 @@ class TRepeater extends TDataBoundControl implements INamingContainer  	}
  	/**
 -	 * Creates a repeater item instance based on the item type and index.
 -	 * @param integer zero-based item index
 +	 * Creates a repeater item.
 +	 * This method invokes {@link createItem} to create a new repeater item.
 +	 * @param integer zero-based item index.
  	 * @param string item type, may be 'Header', 'Footer', 'Empty', 'Item', 'Separator', 'AlternatingItem'.
 -	 * @return TRepeaterItem created repeater item
 +	 * @return TControl the created item, null if item is not created
  	 */
 -	protected function createItem($itemIndex,$itemType)
 +	private function createItemInternal($itemIndex,$itemType)
  	{
 -		return new TRepeaterItem($itemIndex,$itemType);
 +		if(($item=$this->createItem($itemIndex,$itemType))!==null)
 +		{
 +			$param=new TRepeaterItemEventParameter($item);
 +			$this->onItemCreated($param);
 +			$this->getControls()->add($item);
 +			return $item;
 +		}
 +		else
 +			return null;
  	}
  	/**
 -	 * Creates a repeater item and does databinding if needed.
 +	 * Creates a repeater item and performs databinding.
  	 * This method invokes {@link createItem} to create a new repeater item.
  	 * @param integer zero-based item index.
  	 * @param string item type, may be 'Header', 'Footer', 'Empty', 'Item', 'Separator', 'AlternatingItem'.
 -	 * @param boolean whether to do databinding for the item
  	 * @param mixed data to be associated with the item
 -	 * @return TRepeaterItem the created item
 +	 * @return TControl the created item, null if item is not created
  	 */
 -	private function createItemInternal($itemIndex,$itemType,$dataBind,$dataItem)
 +	private function createItemWithDataInternal($itemIndex,$itemType,$dataItem)
  	{
 -		$item=$this->createItem($itemIndex,$itemType);
 -		$this->initializeItem($item);
 -		$param=new TRepeaterItemEventParameter($item);
 -		if($dataBind)
 +		if(($item=$this->createItem($itemIndex,$itemType))!==null)
  		{
 -			$item->setDataItem($dataItem);
 +			$param=new TRepeaterItemEventParameter($item);
 +			if($item instanceof IDataRenderer)
 +				$item->setData($dataItem);
  			$this->onItemCreated($param);
  			$this->getControls()->add($item);
  			$item->dataBind();
  			$this->onItemDataBound($param);
 -			$item->setDataItem(null);
 +			return $item;
  		}
  		else
 -		{
 -			$this->onItemCreated($param);
 -			$this->getControls()->add($item);
 -		}
 -		return $item;
 +			return null;
  	}
  	/**
 -	 * Initializes a repeater item.
 -	 * The item is added as a child of the repeater and the corresponding
 -	 * template is instantiated within the item.
 -	 * @param TRepeaterItem item to be initialized
 +	 * Creates a repeater item instance based on the item type and index.
 +	 * @param integer zero-based item index
 +	 * @param string item type, may be 'Header', 'Footer', 'Empty', 'Item', 'Separator', 'AlternatingItem'.
 +	 * @return TControl created repeater item
  	 */
 -	protected function initializeItem($item)
 +	protected function createItem($itemIndex,$itemType)
  	{
  		$template=null;
 -		switch($item->getItemType())
 +		$classPath=null;
 +		switch($itemType)
  		{
 -			case TListItemType::Header: $template=$this->_headerTemplate; break;
 -			case TListItemType::Footer: $template=$this->_footerTemplate; break;
 -			case TListItemType::Item  : $template=$this->_itemTemplate; break;
 -			case TListItemType::Separator : $template=$this->_separatorTemplate; break;
 -			case TListItemType::AlternatingItem : $template=$this->_alternatingItemTemplate===null ? $this->_itemTemplate : $this->_alternatingItemTemplate; break;
 +			case TListItemType::Item :
 +				$classPath=$this->getItemRenderer();
 +				$template=$this->_itemTemplate;
 +				break;
 +			case TListItemType::AlternatingItem :
 +				if(($classPath=$this->getAlternatingItemRenderer())==='')
 +					$classPath=$this->getItemRenderer();
 +				$template=$this->_alternatingItemTemplate===null ? $this->_itemTemplate : $this->_alternatingItemTemplate;
 +				break;
 +			case TListItemType::Header :
 +				$classPath=$this->getHeaderRenderer();
 +				$template=$this->_headerTemplate;
 +				break;
 +			case TListItemType::Footer :
 +				$classPath=$this->getFooterRenderer();
 +				$template=$this->_footerTemplate;
 +				break;
 +			case TListItemType::Separator :
 +				$classPath=$this->getSeparatorRenderer();
 +				$template=$this->_separatorTemplate;
 +				break;
 +			default:
 +				throw new TInvalidDataValueException('repeater_itemtype_unknown',$itemType);
  		}
 -		if($template!==null)
 +		if($classPath!=='')
 +		{
 +			$item=Prado::createComponent($classPath);
 +			if($item instanceof IItemDataRenderer)
 +			{
 +				$item->setItemIndex($itemIndex);
 +				$item->setItemType($itemType);
 +			}
 +		}
 +		else if($template!==null)
 +		{
 +			$item=new TRepeaterItem;
 +			$item->setItemIndex($itemIndex);
 +			$item->setItemType($itemType);
  			$template->instantiateIn($item);
 +		}
 +		else
 +			$item=null;
 +
 +		return $item;
 +	}
 +
 +	/**
 +	 * Creates empty repeater content.
 +	 */
 +	protected function createEmptyContent()
 +	{
 +		if(($classPath=$this->getEmptyRenderer())!=='')
 +			$this->getControls()->add(Prado::createComponent($classPath));
 +		else if($this->_emptyTemplate!==null)
 +			$this->_emptyTemplate->instantiateIn($this);
  	}
  	/**
 @@ -413,21 +620,19 @@ class TRepeater extends TDataBoundControl implements INamingContainer  		if(($itemCount=$this->getViewState('ItemCount',0))>0)
  		{
  			$items=$this->getItems();
 -			$hasSeparator=$this->_separatorTemplate!==null;
 -			if($this->_headerTemplate!==null)
 -				$this->_header=$this->createItemInternal(-1,TListItemType::Header,false,null);
 +			$hasSeparator=$this->_separatorTemplate!==null || $this->getSeparatorRenderer()!=='';
 +			$this->_header=$this->createItemInternal(-1,TListItemType::Header);
  			for($i=0;$i<$itemCount;++$i)
  			{
  				if($hasSeparator && $i>0)
 -					$this->createItemInternal($i-1,TListItemType::Separator,false,null);
 +					$this->createItemInternal($i-1,TListItemType::Separator);
  				$itemType=$i%2==0?TListItemType::Item : TListItemType::AlternatingItem;
  				$items->add($this->createItemInternal($i,$itemType,false,null));
  			}
 -			if($this->_footerTemplate!==null)
 -				$this->_footer=$this->createItemInternal(-1,TListItemType::Footer,false,null);
 +			$this->_footer=$this->createItemInternal(-1,TListItemType::Footer);
  		}
 -		else if($this->_emptyTemplate!==null)
 -			$this->_emptyTemplate->instantiateIn($this);
 +		else
 +			$this->createEmptyContent();
  		$this->clearChildState();
  	}
 @@ -447,35 +652,32 @@ class TRepeater extends TDataBoundControl implements INamingContainer  		$items=$this->getItems();
  		$itemIndex=0;
 -		$hasSeparator=$this->_separatorTemplate!==null;
 +		$hasSeparator=$this->_separatorTemplate!==null || $this->getSeparatorRenderer()!=='';
  		foreach($data as $key=>$dataItem)
  		{
  			if($keyField!=='')
  				$keys->add($this->getDataFieldValue($dataItem,$keyField));
  			else
  				$keys->add($key);
 -			if($itemIndex===0 && $this->_headerTemplate!==null)
 -				$this->_header=$this->createItemInternal(-1,TListItemType::Header,true,null);
 +			if($itemIndex===0)
 +				$this->_header=$this->createItemWithDataInternal(-1,TListItemType::Header,null);
  			if($hasSeparator && $itemIndex>0)
 -				$this->createItemInternal($itemIndex-1,TListItemType::Separator,true,null);
 +				$this->createItemWithDataInternal($itemIndex-1,TListItemType::Separator,null);
  			$itemType=$itemIndex%2==0?TListItemType::Item : TListItemType::AlternatingItem;
 -			$items->add($this->createItemInternal($itemIndex,$itemType,true,$dataItem));
 +			$items->add($this->createItemWithDataInternal($itemIndex,$itemType,$dataItem));
  			$itemIndex++;
  		}
 -		if($itemIndex>0 && $this->_footerTemplate!==null)
 -			$this->_footer=$this->createItemInternal(-1,TListItemType::Footer,true,null);
 -		if($itemIndex===0 && $this->_emptyTemplate!==null)
 -		{
 -			$this->_emptyTemplate->instantiateIn($this);
 -			$this->dataBindChildren();
 -		}
 +		if($itemIndex>0)
 +			$this->_footer=$this->createItemWithDataInternal(-1,TListItemType::Footer,null);
 +		else
 +			$this->createEmptyContent();
  		$this->setViewState('ItemCount',$itemIndex,0);
  	}
  	/**
  	 * This method overrides parent's implementation to handle
  	 * {@link onItemCommand OnItemCommand} event which is bubbled from
 -	 * {@link TRepeaterItem} child controls.
 +	 * repeater items and their child controls.
  	 * This method should only be used by control developers.
  	 * @param TControl the sender of the event
  	 * @param TEventParameter event parameter
 @@ -496,7 +698,7 @@ class TRepeater extends TDataBoundControl implements INamingContainer  	 * Raises <b>OnItemCreated</b> event.
  	 * This method is invoked after a repeater item is created and instantiated with
  	 * template, but before added to the page hierarchy.
 -	 * The {@link TRepeaterItem} control responsible for the event
 +	 * The repeater item control responsible for the event
  	 * can be determined from the event parameter.
  	 * If you override this method, be sure to call parent's implementation
  	 * so that event handlers have chance to respond to the event.
 @@ -510,7 +712,7 @@ class TRepeater extends TDataBoundControl implements INamingContainer  	/**
  	 * Raises <b>OnItemDataBound</b> event.
  	 * This method is invoked right after an item is data bound.
 -	 * The {@link TRepeaterItem} control responsible for the event
 +	 * The repeater item control responsible for the event
  	 * can be determined from the event parameter.
  	 * If you override this method, be sure to call parent's implementation
  	 * so that event handlers have chance to respond to the event.
 @@ -524,11 +726,11 @@ class TRepeater extends TDataBoundControl implements INamingContainer  	/**
  	 * Raises <b>OnItemCommand</b> event.
  	 * This method is invoked after a button control in
 -	 * a template raises <b>Command</b> event.
 -	 * The {@link TRepeaterItem} control responsible for the event
 +	 * a template raises <b>OnCommand</b> event.
 +	 * The repeater control responsible for the event
  	 * can be determined from the event parameter.
  	 * The event parameter also contains the information about
 -	 * the initial sender of the <b>Command</b> event, command name
 +	 * the initial sender of the <b>OnCommand</b> event, command name
  	 * and command parameter.
  	 * You may override this method to provide customized event handling.
  	 * Be sure to call parent's implementation so that
 @@ -572,22 +774,22 @@ class TRepeater extends TDataBoundControl implements INamingContainer  class TRepeaterItemEventParameter extends TEventParameter
  {
  	/**
 -	 * The TRepeaterItem control responsible for the event.
 -	 * @var TRepeaterItem
 +	 * The repeater item control responsible for the event.
 +	 * @var TControl
  	 */
  	private $_item=null;
  	/**
  	 * Constructor.
 -	 * @param TRepeaterItem repeater item related with the corresponding event
 +	 * @param TControl repeater item related with the corresponding event
  	 */
 -	public function __construct(TRepeaterItem $item)
 +	public function __construct($item)
  	{
  		$this->_item=$item;
  	}
  	/**
 -	 * @return TRepeaterItem repeater item related with the corresponding event
 +	 * @return TControl repeater item related with the corresponding event
  	 */
  	public function getItem()
  	{
 @@ -613,17 +815,17 @@ class TRepeaterItemEventParameter extends TEventParameter  class TRepeaterCommandEventParameter extends TCommandEventParameter
  {
  	/**
 -	 * @var TRepeaterItem the TRepeaterItem control responsible for the event.
 +	 * @var TControl the repeater item control responsible for the event.
  	 */
  	private $_item=null;
  	/**
 -	 * @var TControl the control originally raises the <b>Command</b> event.
 +	 * @var TControl the control originally raises the <b>OnCommand</b> event.
  	 */
  	private $_source=null;
  	/**
  	 * Constructor.
 -	 * @param TRepeaterItem repeater item responsible for the event
 +	 * @param TControl repeater item responsible for the event
  	 * @param TControl original event sender
  	 * @param TCommandEventParameter original event parameter
  	 */
 @@ -635,7 +837,7 @@ class TRepeaterCommandEventParameter extends TCommandEventParameter  	}
  	/**
 -	 * @return TRepeaterItem the TRepeaterItem control responsible for the event.
 +	 * @return TControl the repeater item control responsible for the event.
  	 */
  	public function getItem()
  	{
 @@ -643,7 +845,7 @@ class TRepeaterCommandEventParameter extends TCommandEventParameter  	}
  	/**
 -	 * @return TControl the control originally raises the <b>Command</b> event.
 +	 * @return TControl the control originally raises the <b>OnCommand</b> event.
  	 */
  	public function getCommandSource()
  	{
 @@ -665,35 +867,154 @@ class TRepeaterCommandEventParameter extends TCommandEventParameter   * @package System.Web.UI.WebControls
   * @since 3.0
   */
 -class TRepeaterItem extends TControl implements INamingContainer
 +class TRepeaterItem extends TControl implements INamingContainer, IItemDataRenderer
  {
  	/**
  	 * index of the data item in the Items collection of repeater
  	 */
 -	private $_itemIndex='';
 +	private $_itemIndex;
  	/**
  	 * type of the TRepeaterItem
  	 * @var TListItemType
  	 */
  	private $_itemType;
  	/**
 -	 * value of the data item
 +	 * data associated with this item
  	 * @var mixed
  	 */
 -	private $_dataItem=null;
 +	private $_data;
  	/**
 -	 * Constructor.
 -	 * @param integer zero-based index of the item in the item collection of repeater
 -	 * @param TListItemType item type
 +	 * @return TListItemType item type
 +	 */
 +	public function getItemType()
 +	{
 +		return $this->_itemType;
 +	}
 +
 +	/**
 +	 * @param TListItemType item type.
 +	 */
 +	public function setItemType($value)
 +	{
 +		$this->_itemType=TPropertyValue::ensureEnum($value,'TListItemType');
 +	}
 +
 +	/**
 +	 * Returns a value indicating the zero-based index of the item in the corresponding data control's item collection.
 +	 * If the item is not in the collection (e.g. it is a header item), it returns -1.
 +	 * @return integer zero-based index of the item.
 +	 */
 +	public function getItemIndex()
 +	{
 +		return $this->_itemIndex;
 +	}
 +
 +	/**
 +	 * Sets the zero-based index for the item.
 +	 * If the item is not in the item collection (e.g. it is a header item), -1 should be used.
 +	 * @param integer zero-based index of the item.
 +	 */
 +	public function setItemIndex($value)
 +	{
 +		$this->_itemIndex=TPropertyValue::ensureInteger($value);
 +	}
 +
 +	/**
 +	 * @return mixed data associated with the item
 +	 */
 +	public function getData()
 +	{
 +		return $this->_data;
 +	}
 +
 +	/**
 +	 * @param mixed data to be associated with the item
 +	 */
 +	public function setData($value)
 +	{
 +		$this->_data=$value;
 +	}
 +
 +	/**
 +	 * This property is deprecated since v3.1.0.
 +	 * @return mixed data associated with the item
 +	 * @deprecated deprecated since v3.1.0. Use {@link getData} instead.
 +	 */
 +	public function getDataItem()
 +	{
 +		return $this->getData();
 +	}
 +
 +	/**
 +	 * This property is deprecated since v3.1.0.
 +	 * @param mixed data to be associated with the item
 +	 * @deprecated deprecated since version 3.1.0. Use {@link setData} instead.
  	 */
 -	public function __construct($itemIndex,$itemType)
 +	public function setDataItem($value)
  	{
 -		$this->_itemIndex=$itemIndex;
 -		$this->setItemType($itemType);
 +		return $this->setData($value);
  	}
  	/**
 +	 * This method overrides parent's implementation by wrapping event parameter
 +	 * for <b>OnCommand</b> event with item information.
 +	 * @param TControl the sender of the event
 +	 * @param TEventParameter event parameter
 +	 * @return boolean whether the event bubbling should stop here.
 +	 */
 +	public function bubbleEvent($sender,$param)
 +	{
 +		if($param instanceof TCommandEventParameter)
 +		{
 +			$this->raiseBubbleEvent($this,new TRepeaterCommandEventParameter($this,$sender,$param));
 +			return true;
 +		}
 +		else
 +			return false;
 +	}
 +}
 +
 +
 +/**
 + * TRepeaterItemRenderer class
 + *
 + * TRepeaterItemRenderer can be used as a convenient base class to
 + * define an item renderer class for {@link TRepeater}.
 + * that implements
 + *
 + * Because TRepeaterItemRenderer extends from {@link TTemplateControl}, derived child classes
 + * can have templates to define their presentational layout.
 + *
 + * TRepeaterItemRenderer implements {@link IItemDataRenderer} interface,
 + * which enables the following properties that are related with data-bound controls:
 + * - {@link getItemIndex ItemIndex}: zero-based index of this control in the repeater item collection.
 + * - {@link getItemType ItemType}: item type of this control, such as TListItemType::AlternatingItem
 + * - {@link getData Data}: data associated with this control
 +
 + * @author Qiang Xue <qiang.xue@gmail.com>
 + * @version $Id$
 + * @package System.Web.UI.WebControls
 + * @since 3.1.0
 + */
 +class TRepeaterItemRenderer extends TTemplateControl implements IItemDataRenderer
 +{
 +	/**
 +	 * index of the data item in the Items collection of repeater
 +	 */
 +	private $_itemIndex;
 +	/**
 +	 * type of the TRepeaterItem
 +	 * @var TListItemType
 +	 */
 +	private $_itemType;
 +	/**
 +	 * data associated with this item
 +	 * @var mixed
 +	 */
 +	private $_data;
 +
 +	/**
  	 * @return TListItemType item type
  	 */
  	public function getItemType()
 @@ -710,7 +1031,9 @@ class TRepeaterItem extends TControl implements INamingContainer  	}
  	/**
 -	 * @return integer zero-based index of the item in the item collection of repeater
 +	 * Returns a value indicating the zero-based index of the item in the corresponding data control's item collection.
 +	 * If the item is not in the collection (e.g. it is a header item), it returns -1.
 +	 * @return integer zero-based index of the item.
  	 */
  	public function getItemIndex()
  	{
 @@ -718,24 +1041,34 @@ class TRepeaterItem extends TControl implements INamingContainer  	}
  	/**
 +	 * Sets the zero-based index for the item.
 +	 * If the item is not in the item collection (e.g. it is a header item), -1 should be used.
 +	 * @param integer zero-based index of the item.
 +	 */
 +	public function setItemIndex($value)
 +	{
 +		$this->_itemIndex=TPropertyValue::ensureInteger($value);
 +	}
 +
 +	/**
  	 * @return mixed data associated with the item
  	 */
 -	public function getDataItem()
 +	public function getData()
  	{
 -		return $this->_dataItem;
 +		return $this->_data;
  	}
  	/**
  	 * @param mixed data to be associated with the item
  	 */
 -	public function setDataItem($value)
 +	public function setData($value)
  	{
 -		$this->_dataItem=$value;
 +		$this->_data=$value;
  	}
  	/**
  	 * This method overrides parent's implementation by wrapping event parameter
 -	 * for <b>Command</b> event with item information.
 +	 * for <b>OnCommand</b> event with item information.
  	 * @param TControl the sender of the event
  	 * @param TEventParameter event parameter
  	 * @return boolean whether the event bubbling should stop here.
 @@ -752,6 +1085,7 @@ class TRepeaterItem extends TControl implements INamingContainer  	}
  }
 +
  /**
   * TRepeaterItemCollection class.
   *
 @@ -766,17 +1100,17 @@ class TRepeaterItemCollection extends TList  {
  	/**
  	 * Inserts an item at the specified position.
 -	 * This overrides the parent implementation by inserting only TRepeaterItem.
 +	 * This overrides the parent implementation by inserting only objects that are descendant of {@link TControl}.
  	 * @param integer the speicified position.
 -	 * @param mixed new item
 -	 * @throws TInvalidDataTypeException if the item to be inserted is not a TRepeaterItem.
 +	 * @param TControl new item
 +	 * @throws TInvalidDataTypeException if the item to be inserted is not a control.
  	 */
  	public function insertAt($index,$item)
  	{
 -		if($item instanceof TRepeaterItem)
 +		if($item instanceof TControl)
  			parent::insertAt($index,$item);
  		else
 -			throw new TInvalidDataTypeException('repeateritemcollection_repeateritem_required');
 +			throw new TInvalidDataTypeException('repeateritemcollection_item_invalid');
  	}
  }
 diff --git a/framework/Web/UI/WebControls/TTableCell.php b/framework/Web/UI/WebControls/TTableCell.php index dad2e69b..a0a10fde 100644 --- a/framework/Web/UI/WebControls/TTableCell.php +++ b/framework/Web/UI/WebControls/TTableCell.php @@ -32,7 +32,7 @@   * @package System.Web.UI.WebControls
   * @since 3.0
   */
 -class TTableCell extends TWebControl
 +class TTableCell extends TWebControl implements IDataRenderer
  {
  	/**
  	 * @return string tag name for the table cell
 @@ -167,6 +167,32 @@ class TTableCell extends TWebControl  	}
  	/**
 +	 * Returns the text content of the table cell.
 +	 * This method is required by {@link IDataRenderer}.
 +	 * It is the same as {@link getText()}.
 +	 * @return string the text content of the table cell.
 +	 * @see getText
 +	 * @since 3.1.0
 +	 */
 +	public function getData()
 +	{
 +		return $this->getText();
 +	}
 +
 +	/**
 +	 * Sets the text content of the table cell.
 +	 * This method is required by {@link IDataRenderer}.
 +	 * It is the same as {@link setText()}.
 +	 * @param string the text content of the table cell.
 +	 * @see setText
 +	 * @since 3.1.0
 +	 */
 +	public function setData($value)
 +	{
 +		$this->setText($value);
 +	}
 +
 +	/**
  	 * Adds attributes to renderer.
  	 * @param THtmlWriter the renderer
  	 */
 diff --git a/framework/Web/UI/WebControls/TTextBox.php b/framework/Web/UI/WebControls/TTextBox.php index e8ad92db..047a3084 100644 --- a/framework/Web/UI/WebControls/TTextBox.php +++ b/framework/Web/UI/WebControls/TTextBox.php @@ -48,7 +48,7 @@   * @package System.Web.UI.WebControls
   * @since 3.0
   */
 -class TTextBox extends TWebControl implements IPostBackDataHandler, IValidatable
 +class TTextBox extends TWebControl implements IPostBackDataHandler, IValidatable, IDataRenderer
  {
  	/**
  	 * Default number of rows (for MultiLine text box)
 @@ -424,6 +424,32 @@ class TTextBox extends TWebControl implements IPostBackDataHandler, IValidatable  	}
  	/**
 +	 * Returns the text content of the TTextBox control.
 +	 * This method is required by {@link IDataRenderer}.
 +	 * It is the same as {@link getText()}.
 +	 * @return string the text content of the TTextBox control.
 +	 * @see getText
 +	 * @since 3.1.0
 +	 */
 +	public function getData()
 +	{
 +		return $this->getText();
 +	}
 +
 +	/**
 +	 * Sets the text content of the TTextBox control.
 +	 * This method is required by {@link IDataRenderer}.
 +	 * It is the same as {@link setText()}.
 +	 * @param string the text content of the TTextBox control.
 +	 * @see setText
 +	 * @since 3.1.0
 +	 */
 +	public function setData($value)
 +	{
 +		$this->setText($value);
 +	}
 +
 +	/**
  	 * @return string safe text content with javascript stripped off
  	 */
  	public function getSafeText()
 diff --git a/framework/interfaces.php b/framework/interfaces.php index f37325c8..48164dc0 100644 --- a/framework/interfaces.php +++ b/framework/interfaces.php @@ -322,4 +322,27 @@ interface ICallbackEventHandler  	public function raiseCallbackEvent($eventArgument);
  }
 +/**
 + * IDataRenderer interface.
 + *
 + * If a control wants to be used a renderer for another data-bound control,
 + * this interface must be implemented.
 + *
 + * @author Qiang Xue <qiang.xue@gmail.com>
 + * @version $Id$
 + * @package System
 + * @since 3.1
 + */
 +interface IDataRenderer
 +{
 +	/**
 +	 * @return mixed the data bound to this object
 +	 */
 +	public function getData();
 +
 +	/**
 +	 * @param mixed the data to be bound to this object
 +	 */
 +	public function setData($value);
 +}
  ?>
\ No newline at end of file  | 
