Esempio n. 1
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 {
                        ExceptionHandler = doNotThrow ? e => { } : (Action <Exception>)null,
                    };
                    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);
        }
Esempio n. 2
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);
 }
Esempio n. 3
0
        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]);
            };
        }
        void SetTemplate(ElementTemplate dt, INode node)
        {
#pragma warning disable 0612
            ((IDataTemplate)dt).LoadTemplate = () => {
#pragma warning restore 0612
                var cnode   = node.Clone();
                var context = new HydratationContext {
                    ParentContext = Context, RootElement = Context.RootElement
                };
                cnode.Accept(new XamlNodeVisitor((n, parent) => n.Parent = parent), node.Parent);                 //set parents for {StaticResource}
                cnode.Accept(new ExpandMarkupsVisitor(context), null);
                cnode.Accept(new NamescopingVisitor(context), null);
                cnode.Accept(new CreateValuesVisitor(context), null);
                cnode.Accept(new RegisterXNamesVisitor(context), null);
                cnode.Accept(new FillResourceDictionariesVisitor(context), null);
                cnode.Accept(new ApplyPropertiesVisitor(context, true), null);
                return(context.Values [cnode]);
            };
        }
        static object GetTargetProperty(object xamlelement, XmlName propertyName, HydratationContext context, IXmlLineInfo lineInfo)
        {
            var localName = propertyName.LocalName;
            //If it's an attached BP, update elementType and propertyName
            var bpOwnerType = xamlelement.GetType();

            GetRealNameAndType(ref bpOwnerType, propertyName.NamespaceURI, ref localName, context, lineInfo);
            var property = GetBindableProperty(bpOwnerType, localName, lineInfo, false);

            if (property != null)
            {
                return(property);
            }

            var elementType  = xamlelement.GetType();
            var propertyInfo = elementType.GetRuntimeProperties().FirstOrDefault(p => p.Name == localName);

            return(propertyInfo);
        }
        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);
        }
Esempio n. 7
0
 public CreateValuesVisitor(HydratationContext context)
 {
     Context = context;
 }
        public static void SetPropertyValue(object xamlelement, XmlName propertyName, object value, object rootElement, INode node, HydratationContext context, IXmlLineInfo lineInfo)
        {
            var       localName       = propertyName.LocalName;
            var       serviceProvider = new XamlServiceProvider(node, context);
            Exception xpe             = null;

            //If it's an attached BP, update elementType and propertyName
            var bpOwnerType = xamlelement.GetType();
            var attached    = GetRealNameAndType(ref bpOwnerType, propertyName.NamespaceURI, ref localName, context, lineInfo);
            var property    = GetBindableProperty(bpOwnerType, localName, lineInfo, false);

            //If the target is an event, connect
            if (xpe == null && TryConnectEvent(xamlelement, localName, value, rootElement, lineInfo, out xpe))
            {
                return;
            }

            //If Value is DynamicResource and it's a BP, SetDynamicResource
            if (xpe == null && TrySetDynamicResource(xamlelement, property, value, lineInfo, out xpe))
            {
                return;
            }

            //If value is BindingBase, SetBinding
            if (xpe == null && TrySetBinding(xamlelement, property, localName, value, lineInfo, out xpe))
            {
                return;
            }

            //If it's a BindableProberty, SetValue
            if (xpe == null && TrySetValue(xamlelement, property, attached, value, lineInfo, serviceProvider, out xpe))
            {
                return;
            }

            //If we can assign that value to a normal property, let's do it
            if (xpe == null && TrySetProperty(xamlelement, localName, value, lineInfo, serviceProvider, out xpe))
            {
                return;
            }

            //If it's an already initialized property, add to it
            if (xpe == null && TryAddToProperty(xamlelement, localName, value, lineInfo, serviceProvider, out xpe))
            {
                return;
            }

            xpe = xpe ?? new XamlParseException($"Cannot assign property \"{localName}\": Property does not exists, or is not assignable, or mismatching type between value and property", lineInfo);
            if (context.DoNotThrowOnExceptions)
            {
                System.Diagnostics.Debug.WriteLine(xpe.Message);
            }
            else
            {
                throw xpe;
            }
        }
 public ApplyPropertiesVisitor(HydratationContext context, bool stopOnResourceDictionary = false)
 {
     Context = context;
     StopOnResourceDictionary = stopOnResourceDictionary;
 }
 public NamescopingVisitor(HydratationContext context)
 {
     Values = context.Values;
 }
 public ExpandMarkupsVisitor(HydratationContext context)
 {
     Context = context;
 }
 public FillResourceDictionariesVisitor(HydratationContext context)
 {
     Context = context;
 }
 public RegisterXNamesVisitor(HydratationContext context)
 {
     Values = context.Values;
 }
        static bool TrySetProperty(object element, string localName, object value, IXmlLineInfo lineInfo, XamlServiceProvider serviceProvider, HydratationContext context, out Exception exception)
        {
            exception = null;

            var        elementType  = element.GetType();
            var        propertyInfo = elementType.GetRuntimeProperties().FirstOrDefault(p => p.Name == localName);
            MethodInfo setter;

            if (propertyInfo == null || !propertyInfo.CanWrite || (setter = propertyInfo.SetMethod) == null)
            {
                return(false);
            }

            if (!IsVisibleFrom(setter, context.RootElement))
            {
                return(false);
            }

            object convertedValue = value.ConvertTo(propertyInfo.PropertyType, () => propertyInfo, serviceProvider);

            if (convertedValue != null && !propertyInfo.PropertyType.IsInstanceOfType(convertedValue))
            {
                return(false);
            }

            setter.Invoke(element, new object [] { convertedValue });
            return(true);
        }
Esempio n. 15
0
        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(addMethod.GetParameters()[0].ParameterType, (Func <TypeConverter>)null, serviceProvider) });
                    return;
                }
            }

            if (context.DoNotThrowOnExceptions)
            {
                System.Diagnostics.Debug.WriteLine(exception.Message);
            }
            else
            {
                throw exception;
            }
        }