From e126c0067e9efee6542d08bf649588e2cf3a5924 Mon Sep 17 00:00:00 2001 From: xue <> Date: Thu, 12 Jan 2006 03:22:03 +0000 Subject: Fixed several issues about viewstate handling. Prado Composer is nearly completed. --- demos/composer/protected/pages/Home.page | 45 ++++++++++----- demos/composer/protected/pages/Home.php | 67 ++++++++++++---------- framework/Web/UI/TControl.php | 36 ++++-------- framework/Web/UI/TTemplateManager.php | 5 +- framework/Web/UI/WebControls/TDataBoundControl.php | 5 +- framework/Web/UI/WebControls/TListControl.php | 19 ++++-- framework/Web/UI/WebControls/TRepeater.php | 36 ++++++++++-- 7 files changed, 129 insertions(+), 84 deletions(-) diff --git a/demos/composer/protected/pages/Home.page b/demos/composer/protected/pages/Home.page index b446abd2..ae4149ee 100644 --- a/demos/composer/protected/pages/Home.page +++ b/demos/composer/protected/pages/Home.page @@ -2,29 +2,31 @@ -class -extends +class +Page->ClassDefinition->ClassName%> + CssClass="slTextBox"/> +extends +Page->ClassDefinition->ParentClass%> + CssClass="slTextBox"/> implements - + - + - @@ -49,11 +51,21 @@ implements + @@ -65,13 +77,18 @@ Event Definitions:
Comments -( -Author Name: -Author Email: -)

+Author Name +Page->ClassDefinition->Author%> + CssClass="slTextBox"/> +Author Email +Page->ClassDefinition->Email%> + CssClass="slTextBox"/> +
 
diff --git a/demos/composer/protected/pages/Home.php b/demos/composer/protected/pages/Home.php
index 3c2b4d22..e0112fd7 100644
--- a/demos/composer/protected/pages/Home.php
+++ b/demos/composer/protected/pages/Home.php
@@ -20,24 +20,29 @@ class Home extends TPage
 			$properties[]=new PropertyDefinition;
 			$properties[]=new PropertyDefinition;
 			$properties[]=new PropertyDefinition;
-			$this->PropertyList->setDataSource($properties);
+			$this->PropertyList->DataSource=$properties;
 			$this->dataBind();
 		}
 	}
 
-	/*
-	public function onLoad($param)
+	protected function refresh()
 	{
-		parent::onLoad($param);
-		if(!$this->IsPostBack)
+		$this->PropertyList->DataSource=$this->ClassDefinition->Properties;
+		$this->dataBind();
+	}
+
+	public function itemAction($sender,$param)
+	{
+		if($param->CommandName==='remove')
 		{
-			$this->PropertyList->setDataSource($this->getInitialProperties());
-			$this->PropertyList->dataBind();
+			$this->ClassDefinition->Properties->removeAt($param->CommandParameter);
 		}
-		else
-			$this->PropertyList->ensureChildControls();
+		else if($param->CommandName==='add')
+		{
+			$this->ClassDefinition->Properties->insert($param->CommandParameter+1,new PropertyDefinition);
+		}
+		$this->refresh();
 	}
-	*/
 
 	public function onLoad($param)
 	{
@@ -45,32 +50,32 @@ class Home extends TPage
 		//if($this->IsPostBack && $this->IsValid)
 		if($this->IsPostBack)
 		{
-			$this->PropertyList->ensureChildControls();
+			$def=$this->ClassDefinition;
+			$def->reset();
+			$def->ClassName=$this->ClassName->Text;
+			$def->ParentClass=$this->ParentClass->Text;
+			$def->Interfaces=$this->Interfaces->Text;
+			$def->Comments=$this->Comments->Text;
+			$def->Author=$this->AuthorName->Text;
+			$def->Email=$this->AuthorEmail->Text;
+			foreach($this->PropertyList->Items as $item)
+			{
+				$property=new PropertyDefinition;
+				$property->Name=$item->PropertyName->Text;
+				$property->Type=$item->PropertyType->Text;
+				$property->DefaultValue=$item->DefaultValue->Text;
+				$property->ReadOnly=$item->ReadOnly->Checked;
+				$property->IsProtected=$item->IsProtected->Checked;
+				$property->Comments=$item->Comments->Text;
+				$property->Storage=$item->Storage->Text;
+				$def->Properties[]=$property;
+			}
 		}
 	}
 
 	public function generateCode($sender,$param)
 	{
-		$def=$this->ClassDefinition;
-		$def->reset();
-		$def->ClassName=$this->ClassName->Text;
-		$def->ParentClass=$this->ParentClass->Text;
-		$def->Interfaces=$this->Interfaces->Text;
-		$def->Comments=$this->Comments->Text;
-		$def->Author=$this->AuthorName->Text;
-		$def->Email=$this->AuthorEmail->Text;
-		foreach($this->PropertyList->Items as $item)
-		{
-			$property=new PropertyDefinition;
-			$property->Name=$item->PropertyName->Text;
-			$property->Type=$item->PropertyType->Text;
-			$property->DefaultValue=$item->DefaultValue->Text;
-			$property->ReadOnly=$item->ReadOnly->Checked;
-			$property->IsProtected=$item->IsProtected->Checked;
-			$property->Comments=$item->Comments->Text;
-			$property->Storage=$item->Storage->Text;
-			$def->Properties[]=$property;
-		}
+		$this->refresh();
 		$writer=Prado::createComponent('System.IO.TTextWriter');
 		$this->ClassDefinition->render($writer);
 		$this->SourceCode->Text=highlight_string($writer->flush(),true);
diff --git a/framework/Web/UI/TControl.php b/framework/Web/UI/TControl.php
index db0e141b..18b7d1e0 100644
--- a/framework/Web/UI/TControl.php
+++ b/framework/Web/UI/TControl.php
@@ -1285,11 +1285,11 @@ class TControl extends TComponent
 	 */
 	final protected function loadStateRecursive(&$state,$needViewState=true)
 	{
-		// A null state means the stateful properties all take default values.
-		// So if the state is enabled, we have to assign the null value.
-		$needViewState=($needViewState && !($this->_flags & self::IS_DISABLE_VIEWSTATE));
-		if(is_array($state))
+		if($state!==null)
 		{
+			// A null state means the stateful properties all take default values.
+			// So if the state is enabled, we have to assign the null value.
+			$needViewState=($needViewState && !($this->_flags & self::IS_DISABLE_VIEWSTATE));
 			if(isset($state[1]))
 			{
 				$this->_rf[self::RF_CONTROLSTATE]=&$state[1];
@@ -1324,24 +1324,11 @@ class TControl extends TComponent
 			}
 			if(!empty($state))
 				$this->_rf[self::RF_CHILD_STATE]=&$state;
+			$this->_stage=self::CS_STATE_LOADED;
+			$this->onLoadState(null);
 		}
-		else
-		{
-			unset($this->_rf[self::RF_CONTROLSTATE]);
-			if($needViewState)
-				$this->_viewState=array();
-			if($this->getHasControls())
-			{
-				foreach($this->_rf[self::RF_CONTROLS] as $control)
-				{
-					$s=null;
-					if($control instanceof TControl)
-						$control->loadStateRecursive($s,$needViewState);
-				}
-			}
-		}
-		$this->onLoadState(null);
-		$this->_stage=self::CS_STATE_LOADED;
+		else  // no state to load and thus no need onLoadState()
+			$this->_stage=self::CS_STATE_LOADED;
 	}
 
 	/**
@@ -1361,14 +1348,13 @@ class TControl extends TComponent
 				if($control instanceof TControl)
 				{
 					$cs=&$control->saveStateRecursive($needViewState);
-					if(!empty($cs))
-						$state[$control->_id]=&$cs;
+					$state[$control->_id]=&$cs;
 				}
 			}
 		}
-		if($needViewState && !empty($this->_viewState))
+		if($needViewState)
 			$state[0]=&$this->_viewState;
-		if(isset($this->_rf[self::RF_CONTROLSTATE]) && !empty($this->_rf[self::RF_CONTROLSTATE]))
+		if(isset($this->_rf[self::RF_CONTROLSTATE]))
 			$state[1]=&$this->_rf[self::RF_CONTROLSTATE];
 		return $state;
 	}
diff --git a/framework/Web/UI/TTemplateManager.php b/framework/Web/UI/TTemplateManager.php
index b6a9abd8..bd838db2 100644
--- a/framework/Web/UI/TTemplateManager.php
+++ b/framework/Web/UI/TTemplateManager.php
@@ -231,10 +231,9 @@ class TTemplate extends TComponent implements ITemplate
 	 * @param TControl the parent control
 	 * @throws TTemplateRuntimeException if an error is encountered during the instantiation.
 	 */
-	public function instantiateIn($tplControl,$page=null)
+	public function instantiateIn($tplControl)
 	{
-		if($page===null)
-			$page=$tplControl->getPage();
+		$page=$tplControl->getPage();
 		$this->_assetManager=$page->getService()->getAssetManager();
 		$controls=array();
 		foreach($this->_tpl as $key=>$object)
diff --git a/framework/Web/UI/WebControls/TDataBoundControl.php b/framework/Web/UI/WebControls/TDataBoundControl.php
index 7d865e0f..ea2a0602 100644
--- a/framework/Web/UI/WebControls/TDataBoundControl.php
+++ b/framework/Web/UI/WebControls/TDataBoundControl.php
@@ -40,6 +40,7 @@ abstract class TDataBoundControl extends TWebControl
 	private $_currentDataSourceValid=false;
 	private $_currentViewIsFromDataSourceID=false;
 	private $_parameters=null;
+	private $_isDataBound=false;
 
 	/**
 	 * @return Traversable data source object, defaults to null.
@@ -131,7 +132,7 @@ abstract class TDataBoundControl extends TWebControl
 	 */
 	protected function getIsDataBound()
 	{
-		return $this->getViewState('IsDataBound',false);
+		return $this->_isDataBound;
 	}
 
 	/**
@@ -139,7 +140,7 @@ abstract class TDataBoundControl extends TWebControl
 	 */
 	protected function setIsDataBound($value)
 	{
-		$this->setViewState('IsDataBound',TPropertyValue::ensureBoolean($value),false);
+		$this->_isDataBound=$value;
 	}
 
 	/**
diff --git a/framework/Web/UI/WebControls/TListControl.php b/framework/Web/UI/WebControls/TListControl.php
index f5619b45..7057e119 100644
--- a/framework/Web/UI/WebControls/TListControl.php
+++ b/framework/Web/UI/WebControls/TListControl.php
@@ -80,7 +80,10 @@ abstract class TListControl extends TDataBoundControl
 	 * @var TListItemCollection item list
 	 */
 	private $_items=null;
-
+	/**
+	 * @var boolean whether items are restored from viewstate
+	 */
+	private $_loadedFromState=false;
 	/**
 	 * @return string tag name of the list control
 	 */
@@ -137,7 +140,8 @@ abstract class TListControl extends TDataBoundControl
 	 */
 	public function addParsedObject($object)
 	{
-		if($object instanceof TListItem)
+		// Do not add items from template if items are loaded from viewstate
+		if(!$this->_loadedFromState && ($object instanceof TListItem))
 			$this->getItems()->add($object);
 	}
 
@@ -190,14 +194,19 @@ abstract class TListControl extends TDataBoundControl
 	}
 
 	/**
-	 * Loads items into from viewstate.
+	 * Loads items from viewstate.
 	 * This method is invoked right after control state is loaded.
 	 * @param mixed event parameter
 	 */
 	protected function onLoadState($param)
 	{
-		$this->_items=new TListItemCollection;
-		$this->_items->loadState($this->getViewState('Items',null));
+		$this->_loadedFromState=true;
+		if(!$this->getIsDataBound())
+		{
+			$this->_items=new TListItemCollection;
+			$this->_items->loadState($this->getViewState('Items',null));
+		}
+		$this->clearViewState('Items');
 	}
 
 	/**
diff --git a/framework/Web/UI/WebControls/TRepeater.php b/framework/Web/UI/WebControls/TRepeater.php
index 5110cc75..342a764b 100644
--- a/framework/Web/UI/WebControls/TRepeater.php
+++ b/framework/Web/UI/WebControls/TRepeater.php
@@ -56,6 +56,10 @@ class TRepeater extends TDataBoundControl implements INamingContainer
 	private $_footer=null;
 	private static $_templates=array();
 
+	public function addParsedObject($object)
+	{
+	}
+
 	/**
 	 * @return string the template string for the item
 	 */
@@ -227,8 +231,8 @@ class TRepeater extends TDataBoundControl implements INamingContainer
 					self::$_templates[$key]=$template;
 				}
 			}
-			$template->instantiateIn($item,$this->getPage());
 			$this->getControls()->add($item);
+			$template->instantiateIn($item);
 		}
 	}
 
@@ -250,14 +254,14 @@ class TRepeater extends TDataBoundControl implements INamingContainer
 		return $item;
 	}
 
-	protected function createChildControls()
+	protected function restoreItemsFromViewState()
 	{
 		$this->getControls()->clear();
 		$items=$this->getItems();
 		$items->clear();
 		$this->_header=null;
 		$this->_footer=null;
-		if(($itemCount=$this->getViewState('ItemCount',null))!==null)
+		if(($itemCount=$this->getViewState('ItemCount',0))>0)
 		{
 			if($this->_headerTemplate!=='')
 				$this->_header=$this->createItemInternal(-1,'Header',false,null);
@@ -275,6 +279,31 @@ class TRepeater extends TDataBoundControl implements INamingContainer
 		$this->clearChildState();
 	}
 
+	/**
+	 * Saves items into viewstate.
+	 * This method is invoked right before control state is to be saved.
+	 * @param mixed event parameter
+	 */
+	protected function onSaveState($param)
+	{
+		if($this->_items)
+			$this->setViewState('ItemCount',$this->_items->getCount(),0);
+		else
+			$this->clearViewState('ItemCount');
+	}
+
+	/**
+	 * Loads items into from viewstate.
+	 * This method is invoked right after control state is loaded.
+	 * @param mixed event parameter
+	 */
+	protected function onLoadState($param)
+	{
+		if(!$this->getIsDataBound())
+			$this->restoreItemsFromViewState();
+		$this->clearViewState('ItemCount');
+	}
+
 	/**
 	 * Performs databinding to populate list items from data source.
 	 * This method is invoked by dataBind().
@@ -307,7 +336,6 @@ class TRepeater extends TDataBoundControl implements INamingContainer
 		}
 		else
 			$this->setViewState('ItemCount',$itemIndex,-1);
-		$this->setChildControlsCreated(true);
 	}
 
 	/**
-- 
cgit v1.2.3

Accessibility Name Type Default Value Storage ModeAccessibility Comments Actions
- Parent->DataItem->IsProtected %> /> - Parent->DataItem->ReadOnly %> /> - Parent->DataItem->Name %> CssClass="slTextBox"/> + Parent->DataItem->IsProtected %> /> + Parent->DataItem->ReadOnly %> /> + Parent->DataItem->Comments %> CssClass="slTextBox"/> - - + Parent->ItemIndex %> /> + Parent->ItemIndex %> />