internal XamlServiceProvider(INode node, HydratationContext context)
		{
			object targetObject;
			if (node != null && node.Parent != null && context.Values.TryGetValue(node.Parent, out targetObject))
				IProvideValueTarget = new XamlValueTargetProvider(targetObject, node, context, null);
			if (context != null)
				IRootObjectProvider = new XamlRootObjectProvider(context.RootElement);
			if (node != null)
			{
				IXamlTypeResolver = new XamlTypeResolver(node.NamespaceResolver, XamlParser.GetElementType,
					context.RootElement.GetType().GetTypeInfo().Assembly);

				var enode = node;
				while (enode != null && !(enode is IElementNode))
					enode = enode.Parent;
				if (enode != null)
					INameScopeProvider = new NameScopeProvider { NameScope = (enode as IElementNode).Namescope };
			}

			var xmlLineInfo = node as IXmlLineInfo;
			if (xmlLineInfo != null)
				IXmlLineInfoProvider = new XmlLineInfoProvider(xmlLineInfo);

			IValueConverterProvider = new ValueConverterProvider();
		}
Beispiel #2
0
 public XamlValueTargetProvider(object targetObject, INode node, HydratationContext context, object targetProperty)
 {
     Context        = context;
     Node           = node;
     TargetObject   = targetObject;
     TargetProperty = targetProperty;
 }
        public void TestFailOnMissingOrWrongConverter()
        {
            var node     = new ValueNode("baz", new MockNameSpaceResolver());
            var bindable = new Bindable();

            Assert.IsNull(bindable.Baz);
            var rootNode = new XamlLoader.RuntimeRootNode(new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests", "Bindable", null), bindable, null)
            {
                Properties =
                {
                    { new XmlName(null, "Baz"), node },
                }
            };
            var context = new HydratationContext {
                RootElement = new Label()
            };

            rootNode.Accept(new CreateValuesVisitor(context), null);
            Assert.Throws <XamlParseException>(() => node.Accept(new ApplyPropertiesVisitor(context), rootNode));
        }
Beispiel #4
0
        internal XamlServiceProvider(INode node, HydratationContext context)
        {
            object targetObject;

            if (node != null && node.Parent != null && context.Values.TryGetValue(node.Parent, out targetObject))
            {
                IProvideValueTarget = new XamlValueTargetProvider(targetObject, node, context, null);
            }
            if (context != null)
            {
                IRootObjectProvider = new XamlRootObjectProvider(context.RootElement);
            }
            if (node != null)
            {
                IXamlTypeResolver = new XamlTypeResolver(node.NamespaceResolver, XamlParser.GetElementType,
                                                         context.RootElement.GetType().GetTypeInfo().Assembly);

                var enode = node;
                while (enode != null && !(enode is IElementNode))
                {
                    enode = enode.Parent;
                }
                if (enode != null)
                {
                    INameScopeProvider = new NameScopeProvider {
                        NameScope = (enode as IElementNode).Namescope
                    }
                }
                ;
            }

            var xmlLineInfo = node as IXmlLineInfo;

            if (xmlLineInfo != null)
            {
                IXmlLineInfoProvider = new XmlLineInfoProvider(xmlLineInfo);
            }

            IValueConverterProvider = new ValueConverterProvider();
        }
        public void TestSetPropertyWithoutConverter()
        {
            var baz      = new Baz();
            var node     = new ValueNode(baz, new MockNameSpaceResolver());
            var bindable = new Bindable();

            Assert.IsNull(bindable.Baz);
            var rootNode = new XamlLoader.RuntimeRootNode(new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests", "Bindable", null), bindable, null)
            {
                Properties =
                {
                    { new XmlName(null, "Baz"), node },
                }
            };
            var context = new HydratationContext {
                RootElement = new Label()
            };

            rootNode.Accept(new CreateValuesVisitor(context), null);
            node.Accept(new ApplyPropertiesVisitor(context), rootNode);
            Assert.AreEqual(baz, bindable.Baz);
        }
        public void TestConvertAttachedBindableProperty()
        {
            var node     = new ValueNode("qux", new MockNameSpaceResolver());
            var bindable = new Bindable();

            Assert.IsNull(Bindable.GetQux(bindable));
            var rootNode = new XamlLoader.RuntimeRootNode(new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests", "Bindable", null), bindable, null)
            {
                Properties =
                {
                    { new XmlName("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests", "Bindable.Qux"), node },
                }
            };
            var context = new HydratationContext {
                RootElement = new Label()
            };

            rootNode.Accept(new CreateValuesVisitor(context), null);
            node.Accept(new ApplyPropertiesVisitor(context), rootNode);
            Assert.IsNotNull(Bindable.GetQux(bindable));
            Assert.That(Bindable.GetQux(bindable), Is.TypeOf <Qux> ());
            Assert.AreEqual("qux", Bindable.GetQux(bindable).Value);
        }
        public void TestConvertWithAttributeOnType()
        {
            var node     = new ValueNode("foobar", new MockNameSpaceResolver());
            var bindable = new Bindable();

            Assert.IsNull(bindable.FooBar);
            var rootNode = new XamlLoader.RuntimeRootNode(new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests", "Bindable", null), bindable, null)
            {
                Properties =
                {
                    { new XmlName(null, "FooBar"), node },
                }
            };
            var context = new HydratationContext {
                RootElement = new Label()
            };

            rootNode.Accept(new CreateValuesVisitor(context), null);
            node.Accept(new ApplyPropertiesVisitor(context), rootNode);

            Assert.IsNotNull(bindable.FooBar);
            Assert.That(bindable.FooBar, Is.TypeOf <FooBar> ());
            Assert.AreEqual("foobar", bindable.FooBar.Value);
        }
Beispiel #8
0
		public static object Create (string xaml, bool doNotThrow = false)
		{
			object inflatedView = null;
			using (var reader = XmlReader.Create (new StringReader (xaml))) {
				while (reader.Read ()) {
					//Skip until element
					if (reader.NodeType == XmlNodeType.Whitespace)
						continue;
					if (reader.NodeType != XmlNodeType.Element) {
						Debug.WriteLine ("Unhandled node {0} {1} {2}", reader.NodeType, reader.Name, reader.Value);
						continue;
					}

					var rootnode = new RuntimeRootNode (new XmlType (reader.NamespaceURI, reader.Name, null), null, (IXmlNamespaceResolver)reader);
					XamlParser.ParseXaml (rootnode, reader);
					var visitorContext = new HydratationContext {
						DoNotThrowOnExceptions = doNotThrow,
					};
					var cvv = new CreateValuesVisitor (visitorContext);
					cvv.Visit ((ElementNode)rootnode, null);
					inflatedView = rootnode.Root = visitorContext.Values [rootnode];
					visitorContext.RootElement = inflatedView as BindableObject;

					Visit (rootnode, visitorContext);
					break;
				}
			}
			return inflatedView;
		}
Beispiel #9
0
		static void Visit (RootNode rootnode, HydratationContext visitorContext)
		{
			rootnode.Accept (new XamlNodeVisitor ((node, parent) => node.Parent = parent), null); //set parents for {StaticResource}
			rootnode.Accept (new ExpandMarkupsVisitor (visitorContext), null);
			rootnode.Accept (new NamescopingVisitor (visitorContext), null); //set namescopes for {x:Reference}
			rootnode.Accept (new CreateValuesVisitor (visitorContext), null);
			rootnode.Accept (new RegisterXNamesVisitor (visitorContext), null);
			rootnode.Accept (new FillResourceDictionariesVisitor (visitorContext), null);
			rootnode.Accept (new ApplyPropertiesVisitor (visitorContext, true), null);
		}
		void SetTemplate(ElementTemplate dt, INode node)
		{
#pragma warning disable 0612
			((IDataTemplate)dt).LoadTemplate = () =>
			{
#pragma warning restore 0612
				var context = new HydratationContext { ParentContext = Context, RootElement = Context.RootElement };
				node.Accept(new ExpandMarkupsVisitor(context), null);
				node.Accept(new NamescopingVisitor(context), null);
				node.Accept(new CreateValuesVisitor(context), null);
				node.Accept(new RegisterXNamesVisitor(context), null);
				node.Accept(new FillResourceDictionariesVisitor(context), null);
				node.Accept(new ApplyPropertiesVisitor(context, true), null);
				return context.Values[node];
			};
		}
		public static void SetPropertyValue(object xamlelement, XmlName propertyName, object value, object rootElement,
			INode node, HydratationContext context, IXmlLineInfo lineInfo)
		{
			var elementType = xamlelement.GetType();
			var localname = propertyName.LocalName;

			var serviceProvider = new XamlServiceProvider(node, context);

			//If it's an attached BP, update elementType and propertyName
			var attached = GetRealNameAndType(ref elementType, propertyName.NamespaceURI, ref localname, context, lineInfo);

			//If the target is an event, connect
			var eventInfo = elementType.GetRuntimeEvent(localname);
			if (eventInfo != null && value is string)
			{
				var methodInfo = rootElement.GetType().GetRuntimeMethods().FirstOrDefault(mi => mi.Name == (string)value);
				if (methodInfo == null) {
					var xpe = new XamlParseException (string.Format ("No method {0} found on type {1}", value, rootElement.GetType ()), lineInfo);
					if (context.DoNotThrowOnExceptions) {
						System.Diagnostics.Debug.WriteLine (xpe.Message);
						return;
					} else
						throw xpe;
				}
				try
				{
					eventInfo.AddEventHandler(xamlelement, methodInfo.CreateDelegate(eventInfo.EventHandlerType, rootElement));
				}
				catch (ArgumentException)
				{
					var xpe = new XamlParseException (string.Format ("Method {0} does not have the correct signature", value), lineInfo);
					if (context.DoNotThrowOnExceptions)
						System.Diagnostics.Debug.WriteLine (xpe.Message);
					else
						throw xpe;
				}

				return;
			}

			var property = GetBindableProperty(elementType, localname, lineInfo, false);

			//If Value is DynamicResource and it's a BP, SetDynamicResource
			if (value is DynamicResource && property != null)
			{
				if (!(xamlelement.GetType()).GetTypeInfo().IsSubclassOf(typeof (BindableObject)))
					throw new XamlParseException(string.Format("{0} is not a BindableObject", xamlelement.GetType().Name), lineInfo);
				((BindableObject)xamlelement).SetDynamicResource(property, ((DynamicResource)value).Key);
				return;
			}

			//If value is BindingBase, and target is a BindableProperty, SetBinding
			if (value is BindingBase && property != null)
			{
				if (!(xamlelement.GetType()).GetTypeInfo().IsSubclassOf(typeof (BindableObject)))
					throw new XamlParseException(string.Format("{0} is not a BindableObject", xamlelement.GetType().Name), lineInfo);

				((BindableObject)xamlelement).SetBinding(property, value as BindingBase);
				return;
			}

			//If it's a BindableProberty, SetValue
			if (property != null)
			{
				if (!(xamlelement.GetType()).GetTypeInfo().IsSubclassOf(typeof (BindableObject)))
					throw new XamlParseException(string.Format("{0} is not a BindableObject", xamlelement.GetType().Name), lineInfo);
				Func<MemberInfo> minforetriever;
				if (attached)
					minforetriever = () => elementType.GetRuntimeMethod("Get" + localname, new[] { typeof (BindableObject) });
				else
					minforetriever = () => elementType.GetRuntimeProperty(localname);

				var convertedValue = value.ConvertTo(property.ReturnType, minforetriever, serviceProvider);

				//SetValue doesn't throw on mismatching type, so check before to get a chance to try the property setting or the collection adding
				var nullable = property.ReturnTypeInfo.IsGenericType &&
				               property.ReturnTypeInfo.GetGenericTypeDefinition() == typeof (Nullable<>);
				if ((convertedValue == null && (!property.ReturnTypeInfo.IsValueType || nullable)) ||
				    (property.ReturnType.IsInstanceOfType(convertedValue)))
				{
					((BindableObject)xamlelement).SetValue(property, convertedValue);
					return;
				}
			}

			var exception = new XamlParseException(
				String.Format("No Property of name {0} found", propertyName.LocalName), lineInfo);

			//If we can assign that value to a normal property, let's do it
			var propertyInfo = elementType.GetRuntimeProperties().FirstOrDefault(p => p.Name == localname);
			MethodInfo setter;
			if (propertyInfo != null && propertyInfo.CanWrite && (setter = propertyInfo.SetMethod) != null)
			{
				object convertedValue = value.ConvertTo(propertyInfo.PropertyType, () => propertyInfo, serviceProvider);
				if (convertedValue == null || propertyInfo.PropertyType.IsInstanceOfType(convertedValue))
				{
					try
					{
						setter.Invoke(xamlelement, new[] { convertedValue });
						return;
					}
					catch (ArgumentException)
					{
					}
				}
				else
				{
					exception = new XamlParseException(
						String.Format("Cannot assign property \"{0}\": type mismatch between \"{1}\" and \"{2}\"", propertyName.LocalName,
							value.GetType(), propertyInfo.PropertyType), lineInfo);
				}
			}

			//If it's an already initialized property, add to it
			MethodInfo getter;
			if (propertyInfo != null && propertyInfo.CanRead && (getter = propertyInfo.GetMethod) != null)
			{
				IEnumerable collection;
				MethodInfo addMethod;
				if ((collection = getter.Invoke(xamlelement, new object[] { }) as IEnumerable) != null
				    &&
				    (addMethod =
					    collection.GetType().GetRuntimeMethods().First(mi => mi.Name == "Add" && mi.GetParameters().Length == 1)) !=
				    null)
				{
					addMethod.Invoke(collection,
						new[] { value.ConvertTo(propertyInfo.PropertyType, (Func<TypeConverter>)null, serviceProvider) });
					return;
				}
			}

			if (context.DoNotThrowOnExceptions)
				System.Diagnostics.Debug.WriteLine (exception.Message);
			else
				throw exception;
		}
		static bool GetRealNameAndType(ref Type elementType, string namespaceURI, ref string localname,
			HydratationContext context, IXmlLineInfo lineInfo)
		{
			var dotIdx = localname.IndexOf('.');
			if (dotIdx > 0)
			{
				var typename = localname.Substring(0, dotIdx);
				localname = localname.Substring(dotIdx + 1);
				XamlParseException xpe;
				elementType = XamlParser.GetElementType(new XmlType(namespaceURI, typename, null), lineInfo,
					context.RootElement.GetType().GetTypeInfo().Assembly, out xpe);
				if (xpe != null)
					throw xpe;
				return true;
			}
			return false;
		}
		public ApplyPropertiesVisitor(HydratationContext context, bool stopOnResourceDictionary = false)
		{
			Context = context;
			StopOnResourceDictionary = stopOnResourceDictionary;
		}
		public XamlValueTargetProvider(object targetObject, INode node, HydratationContext context, object targetProperty)
		{
			Context = context;
			Node = node;
			TargetObject = targetObject;
			TargetProperty = targetProperty;
		}
		public void TestFailOnMissingOrWrongConverter ()
		{
			var node = new ValueNode ("baz", new MockNameSpaceResolver());
			var bindable = new Bindable ();

			Assert.IsNull (bindable.Baz);
			var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable, null) {
				Properties = {
					{ new XmlName (null, "Baz"), node },
				}
			};
			var context = new HydratationContext { RootElement = new Label () };
			rootNode.Accept (new CreateValuesVisitor (context), null);
			Assert.Throws<XamlParseException>(()=> node.Accept (new ApplyPropertiesVisitor (context), rootNode));
		}
		public RegisterXNamesVisitor(HydratationContext context)
		{
			Values = context.Values;
		}
		public CreateValuesVisitor(HydratationContext context)
		{
			Context = context;
		}
		public NamescopingVisitor(HydratationContext context)
		{
			Values = context.Values;
		}
		public void TestConvertAttachedBindableProperty ()
		{
			var node = new ValueNode ("qux", new MockNameSpaceResolver());
			var bindable = new Bindable ();

			Assert.IsNull (Bindable.GetQux (bindable));
			var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable, null) {
				Properties = {
					{ new XmlName ("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests", "Bindable.Qux"), node },
				}
			};
			var context = new HydratationContext { RootElement = new Label () };
			rootNode.Accept (new CreateValuesVisitor (context), null);
			node.Accept (new ApplyPropertiesVisitor (context), rootNode);
			Assert.IsNotNull (Bindable.GetQux (bindable));
			Assert.That (Bindable.GetQux (bindable), Is.TypeOf<Qux> ());
			Assert.AreEqual ("qux", Bindable.GetQux (bindable).Value);
		}
		public void TestSetPropertyWithoutConverter ()
		{
			var baz = new Baz ();
			var node = new ValueNode (baz, new MockNameSpaceResolver());
			var bindable = new Bindable ();

			Assert.IsNull (bindable.Baz);
			var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable, null) {
				Properties = {
					{ new XmlName (null, "Baz"), node },
				}
			};
			var context = new HydratationContext { RootElement = new Label () };
			rootNode.Accept (new CreateValuesVisitor(context), null);
			node.Accept (new ApplyPropertiesVisitor (context), rootNode);
			Assert.AreEqual (baz, bindable.Baz);
		
		}
		public void TestConvertWithAttributeOnType ()
		{
			var node = new ValueNode ("foobar", new MockNameSpaceResolver());
			var bindable = new Bindable ();

			Assert.IsNull (bindable.FooBar);
			var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable, null) {
				Properties = {
					{ new XmlName (null, "FooBar"), node },
				}
			};
			var context = new HydratationContext { RootElement = new Label () };
			rootNode.Accept (new CreateValuesVisitor (context), null);
			node.Accept (new ApplyPropertiesVisitor (context), rootNode);

			Assert.IsNotNull (bindable.FooBar);
			Assert.That (bindable.FooBar, Is.TypeOf<FooBar> ());
			Assert.AreEqual ("foobar", bindable.FooBar.Value);
		}