Browse Source

2005-04-15 Lluis Sanchez Gual <[email protected]>

	* TemplateControlCompiler.cs: 


svn path=/trunk/mcs/; revision=43075
Lluis Sanchez 21 years ago
parent
commit
3088a4ad24

+ 4 - 0
mcs/class/System.Web/System.Web.Compilation/ChangeLog

@@ -1,3 +1,7 @@
+2005-04-15  Lluis Sanchez Gual <[email protected]>
+
+	* TemplateControlCompiler.cs: 
+
 2005-04-14  Lluis Sanchez Gual <[email protected]>
 
 	* TemplateControlCompiler.cs: Use the new BindingContainerType

+ 112 - 1
mcs/class/System.Web/System.Web.Compilation/TemplateControlCompiler.cs

@@ -38,6 +38,10 @@ using System.Text;
 using System.Web;
 using System.Web.UI;
 using System.ComponentModel.Design.Serialization;
+#if NET_2_0
+using System.Collections.Specialized;
+using System.Text.RegularExpressions;
+#endif
 
 namespace System.Web.Compilation
 {
@@ -58,6 +62,10 @@ namespace System.Web.Compilation
 		static CodeVariableReferenceExpression ctrlVar = new CodeVariableReferenceExpression ("__ctrl");
 		static Type [] arrayString = new Type [] {typeof (string)};
 		static Type [] arrayStringCultureInfo = new Type [] {typeof (string), typeof (CultureInfo)};
+		
+#if NET_2_0
+		static Regex bindRegex = new Regex (@"Bind\s*\(""(.*?)""\)\s*%>", RegexOptions.Compiled);
+#endif
 
 		public TemplateControlCompiler (TemplateControlParser parser)
 			: base (parser)
@@ -293,6 +301,31 @@ namespace System.Web.Compilation
 			string str = value.Trim ();
 			return (str.StartsWith ("<%#") && str.EndsWith ("%>"));
 		}
+
+#if NET_2_0
+		void RegisterBindingInfo (ControlBuilder builder, string propName, ref string value)
+		{
+			string str = value.Trim ();
+			str = str.Substring (3).Trim ();	// eats "<%#"
+			if (str.StartsWith ("Bind")) {
+				Match match = bindRegex.Match (str);
+				if (match.Success) {
+					string bindingName = match.Groups [1].Value;
+					
+					TemplateBuilder templateBuilder = builder.ParentTemplateBuilder;
+					if (templateBuilder == null || templateBuilder.BindingDirection == BindingDirection.OneWay)
+						throw new HttpException ("Bind expression not allowed in this context.");
+						
+					string id = builder.attribs ["ID"] as string;
+					if (id == null)
+						throw new HttpException ("Control of type '" + builder.ControlType + "' using two-way binding on property '" + propName + "' must have an ID.");
+					
+					templateBuilder.RegisterBoundProperty (builder.ControlType, propName, id, bindingName);
+					value = "<%# Eval" + str.Substring (4);
+				}
+			}
+		}
+#endif
 		
 		bool ProcessPropertiesAndFields (ControlBuilder builder, MemberInfo member, string id, string attValue)
 		{
@@ -312,6 +345,9 @@ namespace System.Web.Compilation
 			}
 
 			if (0 == String.Compare (member.Name, id, true)){
+#if NET_2_0
+				if (isDataBound) RegisterBindingInfo (builder, member.Name, ref attValue);
+#endif
 				AddCodeForPropertyOrField (builder, type, member.Name, attValue, member, isDataBound);
 				return true;
 			}
@@ -342,6 +378,9 @@ namespace System.Web.Compilation
 				else
 					value = attValue;
 
+#if NET_2_0
+				if (isDataBound) RegisterBindingInfo (builder, member.Name + "." + subprop.Name, ref attValue);
+#endif
 				AddCodeForPropertyOrField (builder, subprop.PropertyType,
 						 member.Name + "." + subprop.Name,
 						 value, subprop, isDataBound);
@@ -524,6 +563,71 @@ namespace System.Web.Compilation
 		}
 
 #if NET_2_0
+		void AddBindableTemplateInvocation (CodeMemberMethod method, string name, string methodName, string extractMethodName)
+		{
+			CodePropertyReferenceExpression prop = new CodePropertyReferenceExpression (ctrlVar, name);
+
+			CodeObjectCreateExpression newBuild = new CodeObjectCreateExpression (typeof (BuildTemplateMethod));
+			newBuild.Parameters.Add (new CodeMethodReferenceExpression (thisRef, methodName));
+
+			CodeObjectCreateExpression newExtract = new CodeObjectCreateExpression (typeof (ExtractTemplateValuesMethod));
+			newExtract.Parameters.Add (new CodeMethodReferenceExpression (thisRef, extractMethodName));
+
+			CodeObjectCreateExpression newCompiled = new CodeObjectCreateExpression (typeof (CompiledBindableTemplateBuilder));
+			newCompiled.Parameters.Add (newBuild);
+			newCompiled.Parameters.Add (newExtract);
+			
+			CodeAssignStatement assign = new CodeAssignStatement (prop, newCompiled);
+			method.Statements.Add (assign);
+		}
+		
+		string CreateExtractValuesMethod (TemplateBuilder builder)
+		{
+			CodeMemberMethod method = new CodeMemberMethod ();
+			method.Name = "__ExtractValues_" + builder.ID;
+			method.Attributes = MemberAttributes.Private | MemberAttributes.Final;
+			method.ReturnType = new CodeTypeReference (typeof(IOrderedDictionary));
+			
+			CodeParameterDeclarationExpression arg = new CodeParameterDeclarationExpression ();
+			arg.Type = new CodeTypeReference (typeof (Control));
+			arg.Name = "__container";
+			method.Parameters.Add (arg);
+			mainClass.Members.Add (method);
+			
+			CodeObjectCreateExpression newTable = new CodeObjectCreateExpression ();
+			newTable.CreateType = new CodeTypeReference (typeof(OrderedDictionary));
+			method.Statements.Add (new CodeVariableDeclarationStatement (typeof(OrderedDictionary), "__table", newTable));
+			CodeVariableReferenceExpression tableExp = new CodeVariableReferenceExpression ("__table");
+			
+			if (builder.Bindings != null) {
+				foreach (TemplateBinding binding in builder.Bindings) {
+					CodeVariableDeclarationStatement dec = new CodeVariableDeclarationStatement (binding.ControlType, binding.ControlId);
+					method.Statements.Add (dec);
+					CodeVariableReferenceExpression cter = new CodeVariableReferenceExpression ("__container");
+					CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (cter, "FindControl");
+					invoke.Parameters.Add (new CodePrimitiveExpression (binding.ControlId));
+					
+					CodeAssignStatement assign = new CodeAssignStatement ();
+					CodeVariableReferenceExpression control = new CodeVariableReferenceExpression (binding.ControlId); 
+					assign.Left = control;
+					assign.Right = new CodeCastExpression (binding.ControlType, invoke);
+					method.Statements.Add (assign);
+					
+					CodeConditionStatement sif = new CodeConditionStatement ();
+					sif.Condition = new CodeBinaryOperatorExpression (control, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression (null));
+					
+					assign = new CodeAssignStatement ();
+					assign.Left = new CodeIndexerExpression (tableExp, new CodePrimitiveExpression (binding.FieldName));
+					assign.Right = new CodePropertyReferenceExpression (control, binding.ControlProperty);
+					sif.TrueStatements.Add (assign);
+					method.Statements.Add (sif);
+				}
+			}
+
+			method.Statements.Add (new CodeMethodReturnStatement (tableExp));
+			return method.Name;
+		}
+
 		void AddContentTemplateInvocation (ContentControlBuilder cbuilder, CodeMemberMethod method, string methodName)
 		{
 			CodePropertyReferenceExpression pag = new CodePropertyReferenceExpression (ctrlVar, "Page");
@@ -738,8 +842,15 @@ namespace System.Web.Compilation
 				FlushText (builder, sb);
 
 				if (templates != null) {
-					foreach (ControlBuilder b in templates) {
+					foreach (TemplateBuilder b in templates) {
 						CreateControlTree (b, true, false);
+#if NET_2_0
+						if (b.BindingDirection == BindingDirection.TwoWay) {
+							string extractMethod = CreateExtractValuesMethod (b);
+							AddBindableTemplateInvocation (builder.method, b.TagName, b.method.Name, extractMethod);
+						}
+						else
+#endif
 						AddTemplateInvocation (builder.method, b.TagName, b.method.Name);
 					}
 				}