summaryrefslogtreecommitdiff
path: root/framework/Web/UI/TControl.php
diff options
context:
space:
mode:
Diffstat (limited to 'framework/Web/UI/TControl.php')
-rw-r--r--framework/Web/UI/TControl.php143
1 files changed, 141 insertions, 2 deletions
diff --git a/framework/Web/UI/TControl.php b/framework/Web/UI/TControl.php
index 78c5bdfc..9ede6be5 100644
--- a/framework/Web/UI/TControl.php
+++ b/framework/Web/UI/TControl.php
@@ -122,6 +122,7 @@ class TControl extends TApplicationComponent implements IRenderable, IBindable
const RF_CONTROLSTATE=7; // controlstate
const RF_NAMED_OBJECTS=8; // controls declared with ID on template
const RF_ADAPTER=9; // adapter
+ const RF_AUTO_BINDINGS=10; // auto data bindings
/**
* @var string control ID
@@ -722,7 +723,7 @@ class TControl extends TApplicationComponent implements IRenderable, IBindable
/**
* Sets up the binding between a property (or property path) and an expression.
- * The context of the expression is the control itself.
+ * The context of the expression is the template control (or the control itself if it is a page).
* @param string the property name, or property path
* @param string the expression
*/
@@ -741,6 +742,19 @@ class TControl extends TApplicationComponent implements IRenderable, IBindable
}
/**
+ * Sets up the binding between a property (or property path) and an expression.
+ * Unlike regular databinding, the expression bound by this method
+ * is automatically evaluated during {@link prerenderRecursive()}.
+ * The context of the expression is the template control (or the control itself if it is a page).
+ * @param string the property name, or property path
+ * @param string the expression
+ */
+ public function autoBindProperty($name,$expression)
+ {
+ $this->_rf[self::RF_AUTO_BINDINGS][$name]=$expression;
+ }
+
+ /**
* Performs the databinding for this control.
*/
public function dataBind()
@@ -760,8 +774,24 @@ class TControl extends TApplicationComponent implements IRenderable, IBindable
{
if(isset($this->_rf[self::RF_DATA_BINDINGS]))
{
+ if(($context=$this->getTemplateControl())===null)
+ $context=$this;
foreach($this->_rf[self::RF_DATA_BINDINGS] as $property=>$expression)
- $this->setSubProperty($property,$this->evaluateExpression($expression));
+ $this->setSubProperty($property,$context->evaluateExpression($expression));
+ }
+ }
+
+ /**
+ * Auto databinding properties of the control.
+ */
+ protected function autoDataBindProperties()
+ {
+ if(isset($this->_rf[self::RF_AUTO_BINDINGS]))
+ {
+ if(($context=$this->getTemplateControl())===null)
+ $context=$this;
+ foreach($this->_rf[self::RF_AUTO_BINDINGS] as $property=>$expression)
+ $this->setSubProperty($property,$context->evaluateExpression($expression));
}
}
@@ -1159,6 +1189,8 @@ class TControl extends TApplicationComponent implements IRenderable, IBindable
{
if($this->_stage<self::CS_LOADED)
{
+ if(($context=$this->getTemplateControl())===null)
+ $context=$this;
if(isset($this->_rf[self::RF_ADAPTER]))
$this->_rf[self::RF_ADAPTER]->onLoad(null);
else
@@ -1167,8 +1199,10 @@ class TControl extends TApplicationComponent implements IRenderable, IBindable
if($this->getHasControls())
{
foreach($this->_rf[self::RF_CONTROLS] as $control)
+ {
if($control instanceof TControl)
$control->loadRecursive();
+ }
}
if($this->_stage<self::CS_LOADED)
$this->_stage=self::CS_LOADED;
@@ -1180,6 +1214,8 @@ class TControl extends TApplicationComponent implements IRenderable, IBindable
*/
protected function preRenderRecursive()
{
+ $this->autoDataBindProperties();
+
if($this->getVisible(false))
{
$this->ensureChildControls();
@@ -1190,8 +1226,12 @@ class TControl extends TApplicationComponent implements IRenderable, IBindable
if($this->getHasControls())
{
foreach($this->_rf[self::RF_CONTROLS] as $control)
+ {
if($control instanceof TControl)
$control->preRenderRecursive();
+ else if($control instanceof TCompositeLiteral)
+ $control->evaluateDynamicContent();
+ }
}
}
$this->_stage=self::CS_PRERENDERED;
@@ -2030,4 +2070,103 @@ class TCommandEventParameter extends TEventParameter
}
}
+
+/**
+ * TCompositeLiteral class
+ *
+ * TCompositeLiteral is used internally by {@link TTemplate} for representing
+ * consecutive static strings, expressions and statements.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $ $Date: $
+ * @package System.Web.UI
+ * @since 3.0
+ */
+class TCompositeLiteral extends TComponent implements IRenderable, IBindable
+{
+ const TYPE_EXPRESSION=0;
+ const TYPE_STATEMENTS=1;
+ const TYPE_DATABINDING=2;
+ private $_container=null;
+ private $_items=array();
+ private $_expressions=array();
+ private $_statements=array();
+ private $_bindings=array();
+
+ /**
+ * Constructor.
+ * @param array list of items to be represented by TCompositeLiteral
+ */
+ public function __construct($items)
+ {
+ $this->_items=array();
+ $this->_expressions=array();
+ $this->_statements=array();
+ foreach($items as $id=>$item)
+ {
+ if(is_array($item))
+ {
+ if($item[0]===self::TYPE_EXPRESSION)
+ $this->_expressions[$id]=$item[1];
+ else if($item[0]===self::TYPE_STATEMENTS)
+ $this->_statements[$id]=$item[1];
+ else if($item[0]===self::TYPE_DATABINDING)
+ $this->_bindings[$id]=$item[1];
+ $this->_items[$id]='';
+ }
+ else
+ $this->_items[$id]=$item;
+ }
+ }
+
+ /**
+ * @return TComponent container of this component. It serves as the evaluation context of expressions and statements.
+ */
+ public function getContainer()
+ {
+ return $this->_container;
+ }
+
+ /**
+ * @param TComponent container of this component. It serves as the evaluation context of expressions and statements.
+ */
+ public function setContainer(TComponent $value)
+ {
+ $this->_container=$value;
+ }
+
+ /**
+ * Evaluates the expressions and/or statements in the component.
+ */
+ public function evaluateDynamicContent()
+ {
+ $context=$this->_container===null?$this:$this->_container;
+ foreach($this->_expressions as $id=>$expression)
+ $this->_items[$id]=$context->evaluateExpression($expression);
+ foreach($this->_statements as $id=>$statement)
+ $this->_items[$id]=$context->evaluateStatements($statement);
+ }
+
+ /**
+ * Performs databindings.
+ * This method is required by {@link IBindable}
+ */
+ public function dataBind()
+ {
+ $context=$this->_container===null?$this:$this->_container;
+ foreach($this->_bindings as $id=>$binding)
+ $this->_items[$id]=$context->evaluateExpression($binding);
+ }
+
+ /**
+ * Renders the content stored in this component.
+ * This method is required by {@link IRenderable}
+ * @param ITextWriter
+ */
+ public function render($writer)
+ {
+ $writer->write(implode('',$this->_items));
+ }
+}
+
?> \ No newline at end of file