예제 #1
0
        /// <summary>
        /// Finds the specified property, or creates it if it doesn't exist.
        /// </summary>
        public XamlProperty FindOrCreateAttachedProperty(Type ownerType, string propertyName)
        {
            if (ownerType == null)
            {
                throw new ArgumentNullException("ownerType");
            }
            if (propertyName == null)
            {
                throw new ArgumentNullException("propertyName");
            }

            foreach (XamlProperty p in properties)
            {
                if (p.IsAttached && p.PropertyTargetType == ownerType && p.PropertyName == propertyName)
                {
                    return(p);
                }
            }
            XamlPropertyInfo info = XamlParser.TryFindAttachedProperty(ownerType, propertyName);

            if (info == null)
            {
                throw new ArgumentException(
                          "The attached property '" + propertyName + "' doesn't exist on " + ownerType.FullName,
                          "propertyName");
            }
            XamlProperty newProperty = new XamlProperty(this, info);

            properties.Add(newProperty);
            return(newProperty);
        }
예제 #2
0
        internal static void ParseObjectAttribute(XamlObject obj, XmlAttribute attribute, bool real)
        {
            XamlPropertyInfo propertyInfo = GetPropertyInfo(obj.Instance, obj.ElementType, attribute,
                                                            obj.OwnerDocument.TypeFinder);
            XamlPropertyValue value = null;

            var valueText = attribute.Value;

            if (valueText.StartsWith("{", StringComparison.Ordinal) &&
                !valueText.StartsWith("{}", StringComparison.Ordinal))
            {
                var xamlObject = MarkupExtensionParser.Parse(valueText, obj, real ? attribute : null);
                value = xamlObject;
            }
            else
            {
                if (real)
                {
                    value = new XamlTextValue(obj.OwnerDocument, attribute);
                }
                else
                {
                    value = new XamlTextValue(obj.OwnerDocument, valueText);
                }
            }

            var property = new XamlProperty(obj, propertyInfo, value);

            obj.AddProperty(property);
        }
예제 #3
0
        internal static XamlPropertyInfo GetPropertyInfo(XamlTypeFinder typeFinder, object elementInstance,
                                                         Type elementType, string xmlNamespace, string localName, bool tryFindAllProperties = false)
        {
            string typeName, propertyName;

            SplitQualifiedIdentifier(localName, out typeName, out propertyName);
            Type propertyType = FindType(typeFinder, xmlNamespace, typeName);

            //Tries to Find All properties, even if they are not attached (For Setters, Bindings, ...)
            if (tryFindAllProperties)
            {
                XamlPropertyInfo propertyInfo = null;
                try
                {
                    propertyInfo = FindProperty(elementInstance, propertyType, propertyName);
                }
                catch (Exception)
                {
                }
                if (propertyInfo != null)
                {
                    return(propertyInfo);
                }
            }

            if (elementType.IsAssignableFrom(propertyType) || propertyType.IsAssignableFrom(elementType))
            {
                return(FindProperty(elementInstance, propertyType, propertyName));
            }
            else
            {
                // This is an attached property
                return(FindAttachedProperty(propertyType, propertyName));
            }
        }
예제 #4
0
        static bool IsElementChildACollectionForProperty(XamlTypeFinder typeFinder, XmlElement element,
                                                         XamlPropertyInfo propertyInfo)
        {
            var nodes = element.ChildNodes.Cast <XmlNode>().Where(x => !(x is XmlWhitespace)).ToList();

            return(nodes.Count == 1 &&
                   propertyInfo.ReturnType.IsAssignableFrom(
                       FindType(typeFinder, nodes[0].NamespaceURI, nodes[0].LocalName)));
        }
예제 #5
0
        static XamlProperty FindExistingXamlProperty(XamlObject obj, XamlPropertyInfo propertyInfo)
        {
            foreach (XamlProperty existing in obj.Properties)
            {
                if (existing.propertyInfo.FullyQualifiedName == propertyInfo.FullyQualifiedName)
                {
                    return(existing);
                }
            }

            throw new XamlLoadException("Existing XamlProperty " + propertyInfo.FullyQualifiedName + " not found.");
        }
예제 #6
0
        // for use by parser only
        internal XamlProperty(XamlObject parentObject, XamlPropertyInfo propertyInfo, XamlPropertyValue propertyValue)
            : this(parentObject, propertyInfo)
        {
            PossiblyNameChanged(null, propertyValue);

            this.propertyValue = propertyValue;
            if (propertyValue != null)
            {
                propertyValue.ParentProperty = this;
            }

            UpdateValueOnInstance();
        }
예제 #7
0
        internal override object GetValueFor(XamlPropertyInfo targetProperty)
        {
            if (ParentProperty == null)
            {
                throw new InvalidOperationException("Cannot call GetValueFor while ParentProperty is null");
            }

            if (targetProperty == null)
            {
                return(this.Text);
            }

            return(XamlParser.CreateObjectFromAttributeText(Text, targetProperty, ParentProperty.ParentObject));
        }
예제 #8
0
 internal override object GetValueFor(XamlPropertyInfo targetProperty)
 {
     if (IsMarkupExtension)
     {
         var value = ProvideValue();
         if (value is string && targetProperty != null && targetProperty.ReturnType != typeof(string))
         {
             return(XamlParser.CreateObjectFromAttributeText((string)value, targetProperty, this));
         }
         return(value);
     }
     else
     {
         return(instance);
     }
 }
예제 #9
0
        static XamlPropertyInfo FindAttachedProperty(Type elementType, string propertyName)
        {
            XamlPropertyInfo pi = TryFindAttachedProperty(elementType, propertyName);

            if (pi == null)
            {
                pi = TryFindAttachedEvent(elementType, propertyName);
            }
            if (pi != null)
            {
                return(pi);
            }
            else
            {
                throw new XamlLoadException("attached property " + elementType.Name + "." + propertyName +
                                            " not found");
            }
        }
예제 #10
0
        internal XamlProperty(XamlObject parentObject, XamlPropertyInfo propertyInfo)
        {
            this.parentObject = parentObject;
            this.propertyInfo = propertyInfo;

            if (propertyInfo.IsCollection)
            {
                isCollection       = true;
                collectionElements = new CollectionElementsCollection(this);
                collectionElements.CollectionChanged += OnCollectionChanged;

                if (propertyInfo.Name.Equals(XamlConstants.ResourcesPropertyName, StringComparison.Ordinal) &&
                    propertyInfo.ReturnType == typeof(ResourceDictionary))
                {
                    isResources = true;
                }
            }
        }
예제 #11
0
        internal static XamlPropertyInfo FindProperty(object elementInstance, Type propertyType, string propertyName)
        {
            PropertyDescriptor propertyInfo = TypeDescriptor.GetProperties(propertyType)[propertyName];

            if (propertyInfo == null && elementInstance != null)
            {
                propertyInfo = TypeDescriptor.GetProperties(elementInstance)
                               .OfType <DependencyPropertyDescriptor>()
                               .FirstOrDefault(x => x.IsAttached && x.Name == propertyName);
            }

            if (propertyInfo != null)
            {
                return(new XamlNormalPropertyInfo(propertyInfo));
            }
            else
            {
                XamlPropertyInfo pi = TryFindAttachedProperty(propertyType, propertyName);
                if (pi != null)
                {
                    return(pi);
                }
            }
            EventDescriptorCollection events;

            if (elementInstance != null)
            {
                events = TypeDescriptor.GetEvents(elementInstance);
            }
            else
            {
                events = TypeDescriptor.GetEvents(propertyType);
            }
            EventDescriptor eventInfo = events[propertyName];

            if (eventInfo != null)
            {
                return(new XamlEventPropertyInfo(eventInfo));
            }

            throw new XamlLoadException("property " + propertyName + " not found");
        }
예제 #12
0
        internal static object CreateObjectFromAttributeText(string valueText, XamlPropertyInfo targetProperty,
                                                             XamlObject scope)
        {
            if (targetProperty.ReturnType == typeof(Uri))
            {
                return(scope.OwnerDocument.TypeFinder.ConvertUriToLocalUri(new Uri(valueText,
                                                                                   UriKind.RelativeOrAbsolute)));
            }
            else if (targetProperty.ReturnType == typeof(ImageSource))
            {
                var uri =
                    scope.OwnerDocument.TypeFinder.ConvertUriToLocalUri(new Uri(valueText, UriKind.RelativeOrAbsolute));
                return(targetProperty.TypeConverter.ConvertFromString(
                           scope.OwnerDocument.GetTypeDescriptorContext(scope), CultureInfo.InvariantCulture, uri.ToString()));
            }

            return(targetProperty.TypeConverter.ConvertFromString(
                       scope.OwnerDocument.GetTypeDescriptorContext(scope),
                       CultureInfo.InvariantCulture, valueText));
        }
        protected override void InsertItem(int index, XamlPropertyValue item)
        {
            XamlPropertyInfo info       = property.propertyInfo;
            object           collection = info.GetValue(property.ParentObject.Instance);

            if (!CollectionSupport.TryInsert(info.ReturnType, collection, item, index))
            {
                CollectionSupport.AddToCollection(info.ReturnType, collection, item);
            }

            item.ParentProperty = property;
            property.InsertNodeInCollection(item.GetNodeForCollection(), index);

            base.InsertItem(index, item);

            if (CollectionChanged != null)
            {
                CollectionChanged(this,
                                  new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
            }
        }
예제 #14
0
 public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
 {
     if (value == null)
     {
         return(null);
     }
     if (value is string)
     {
         XamlTypeResolverProvider xamlTypeResolver =
             (XamlTypeResolverProvider)context.GetService(typeof(XamlTypeResolverProvider));
         if (xamlTypeResolver == null)
         {
             throw new XamlLoadException("XamlTypeResolverProvider not found in type descriptor context.");
         }
         XamlPropertyInfo prop = xamlTypeResolver.ResolveProperty((string)value);
         if (prop == null)
         {
             throw new XamlLoadException("Could not find property " + value + ".");
         }
         XamlDependencyPropertyInfo depProp = prop as XamlDependencyPropertyInfo;
         if (depProp != null)
         {
             return(depProp.DependencyProperty);
         }
         FieldInfo field = prop.TargetType.GetField(prop.Name + "Property",
                                                    BindingFlags.Public | BindingFlags.Static);
         if (field != null && field.FieldType == typeof(DependencyProperty))
         {
             return((DependencyProperty)field.GetValue(null));
         }
         throw new XamlLoadException("Property " + value + " is not a dependency property.");
     }
     else
     {
         return(base.ConvertFrom(context, culture, value));
     }
 }
        protected override void RemoveItem(int index)
        {
            XamlPropertyInfo info       = property.propertyInfo;
            object           collection = info.GetValue(property.ParentObject.Instance);

            if (!CollectionSupport.RemoveItemAt(info.ReturnType, collection, index))
            {
                var propertyValue = this[index];
                CollectionSupport.RemoveItem(info.ReturnType, collection, propertyValue.GetValueFor(info),
                                             propertyValue);
            }

            var item = this[index];

            item.RemoveNodeFromParent();
            item.ParentProperty = null;
            base.RemoveItem(index);

            if (CollectionChanged != null && !isClearing)
            {
                CollectionChanged(this,
                                  new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));
            }
        }
예제 #16
0
 /// <summary>
 /// used internally by the XamlParser.
 /// </summary>
 internal abstract object GetValueFor(XamlPropertyInfo targetProperty);
예제 #17
0
        void ParseObjectChildElementAsPropertyElement(XamlObject obj, XmlElement element,
                                                      XamlPropertyInfo defaultProperty)
        {
            Debug.Assert(element.LocalName.Contains("."));
            // this is a element property syntax

            XamlPropertyInfo propertyInfo = GetPropertyInfo(settings.TypeFinder, obj.Instance, obj.ElementType,
                                                            element.NamespaceURI, element.LocalName);
            bool valueWasSet = false;

            object       collectionInstance = null;
            bool         isElementChildACollectionForProperty = false;
            XamlProperty collectionProperty = null;

            if (propertyInfo.IsCollection)
            {
                if (defaultProperty != null && defaultProperty.FullyQualifiedName == propertyInfo.FullyQualifiedName)
                {
                    foreach (XamlProperty existing in obj.Properties)
                    {
                        if (existing.propertyInfo == defaultProperty)
                        {
                            collectionProperty = existing;
                            break;
                        }
                    }
                }

                if (collectionProperty == null)
                {
                    obj.AddProperty(collectionProperty = new XamlProperty(obj, propertyInfo));
                }

                isElementChildACollectionForProperty =
                    IsElementChildACollectionForProperty(settings.TypeFinder, element, propertyInfo);
                if (isElementChildACollectionForProperty)
                {
                    collectionProperty.ParserSetPropertyElement((XmlElement)element.ChildNodes.Cast <XmlNode>()
                                                                .Where(x => !(x is XmlWhitespace))
                                                                .First());
                }
                else
                {
                    collectionInstance = collectionProperty.propertyInfo.GetValue(obj.Instance);
                    collectionProperty.ParserSetPropertyElement(element);
                    collectionInstance = collectionInstance ??
                                         Activator.CreateInstance(collectionProperty.propertyInfo.ReturnType);
                }
            }

            XmlSpace oldXmlSpace = currentXmlSpace;

            if (element.HasAttribute("xml:space"))
            {
                currentXmlSpace = (XmlSpace)Enum.Parse(typeof(XmlSpace), element.GetAttribute("xml:space"), true);
            }

            foreach (XmlNode childNode in element.ChildNodes)
            {
                currentParsedNode = childNode;
                XamlPropertyValue childValue = ParseValue(childNode);
                if (childValue != null)
                {
                    if (propertyInfo.IsCollection)
                    {
                        if (isElementChildACollectionForProperty)
                        {
                            collectionProperty.PropertyValue = childValue;
                        }
                        else
                        {
                            CollectionSupport.AddToCollection(propertyInfo.ReturnType, collectionInstance, childValue);
                            collectionProperty.ParserAddCollectionElement(element, childValue);
                        }
                    }
                    else
                    {
                        if (valueWasSet)
                        {
                            throw new XamlLoadException("non-collection property may have only one child element");
                        }
                        valueWasSet = true;
                        XamlProperty xp = new XamlProperty(obj, propertyInfo, childValue);
                        xp.ParserSetPropertyElement(element);
                        obj.AddProperty(xp);
                    }
                }
            }

            currentParsedNode = element;

            currentXmlSpace = oldXmlSpace;
        }
예제 #18
0
        XamlObject ParseObject(XmlElement element)
        {
            Type elementType = settings.TypeFinder.GetType(element.NamespaceURI, element.LocalName);

            if (typeof(FrameworkTemplate).IsAssignableFrom(elementType))
            {
                var xamlObj = new XamlObject(document, element, elementType,
                                             TemplateHelper.GetFrameworkTemplate(element, currentXamlObject));
                xamlObj.ParentObject = currentXamlObject;
                return(xamlObj);
            }


            if (elementType == null)
            {
                elementType = settings.TypeFinder.GetType(element.NamespaceURI, element.LocalName + "Extension");
                if (elementType == null)
                {
                    throw new XamlLoadException("Cannot find type " + element.Name);
                }
            }

            XmlSpace   oldXmlSpace      = currentXmlSpace;
            XamlObject parentXamlObject = currentXamlObject;

            if (element.HasAttribute("xml:space"))
            {
                currentXmlSpace = (XmlSpace)Enum.Parse(typeof(XmlSpace), element.GetAttribute("xml:space"), true);
            }

            XamlPropertyInfo defaultProperty = GetDefaultProperty(elementType);

            XamlTextValue initializeFromTextValueInsteadOfConstructor = null;

            if (defaultProperty == null)
            {
                int  numberOfTextNodes = 0;
                bool onlyTextNodes     = true;
                foreach (XmlNode childNode in element.ChildNodes)
                {
                    if (childNode.NodeType == XmlNodeType.Text)
                    {
                        numberOfTextNodes++;
                    }
                    else if (childNode.NodeType == XmlNodeType.Element)
                    {
                        onlyTextNodes = false;
                    }
                }

                if (elementType == typeof(string) && numberOfTextNodes == 0)
                {
                    initializeFromTextValueInsteadOfConstructor = new XamlTextValue(document, string.Empty);
                }
                else if (onlyTextNodes && numberOfTextNodes == 1)
                {
                    foreach (XmlNode childNode in element.ChildNodes)
                    {
                        if (childNode.NodeType == XmlNodeType.Text)
                        {
                            currentParsedNode = childNode;
                            initializeFromTextValueInsteadOfConstructor = (XamlTextValue)ParseValue(childNode);
                        }
                    }
                }
            }

            currentParsedNode = element;

            object instance;

            if (initializeFromTextValueInsteadOfConstructor != null)
            {
                instance = TypeDescriptor.GetConverter(elementType)
                           .ConvertFromString(
                    document.GetTypeDescriptorContext(null),
                    CultureInfo.InvariantCulture,
                    initializeFromTextValueInsteadOfConstructor.Text);
            }
            else
            {
                instance = settings.CreateInstanceCallback(elementType, emptyObjectArray);
            }

            XamlObject obj = new XamlObject(document, element, elementType, instance);

            currentXamlObject = obj;
            obj.ParentObject  = parentXamlObject;

            if (parentXamlObject == null && obj.Instance is DependencyObject)
            {
                NameScope.SetNameScope((DependencyObject)obj.Instance, new NameScope());
            }

            ISupportInitialize iSupportInitializeInstance = instance as ISupportInitialize;

            if (iSupportInitializeInstance != null)
            {
                iSupportInitializeInstance.BeginInit();
            }

            foreach (XmlAttribute attribute in element.Attributes)
            {
                if (attribute.Value.StartsWith("clr-namespace", StringComparison.OrdinalIgnoreCase))
                {
                    // the format is "clr-namespace:<Namespace here>;assembly=<Assembly name here>"
                    var clrNamespace = attribute.Value.Split(new[] { ':', ';', '=' });
                    if (clrNamespace.Length == 4)
                    {
                        // get the assembly name
                        var assembly = settings.TypeFinder.LoadAssembly(clrNamespace[3]);
                        if (assembly != null)
                        {
                            settings.TypeFinder.RegisterAssembly(assembly);
                        }
                    }
                    else
                    {
                        // if no assembly name is there, then load the assembly of the opened file.
                        var assembly = settings.TypeFinder.LoadAssembly(null);
                        if (assembly != null)
                        {
                            settings.TypeFinder.RegisterAssembly(assembly);
                        }
                    }
                }
                if (attribute.NamespaceURI == XamlConstants.XmlnsNamespace)
                {
                    continue;
                }
                if (attribute.Name == "xml:space")
                {
                    continue;
                }
                if (GetAttributeNamespace(attribute) == XamlConstants.XamlNamespace ||
                    GetAttributeNamespace(attribute) == XamlConstants.Xaml2009Namespace)
                {
                    if (attribute.LocalName == "Name")
                    {
                        try
                        {
                            NameScopeHelper.NameChanged(obj, null, attribute.Value);
                        }
                        catch (Exception x)
                        {
                            ReportException(x, attribute);
                        }
                    }
                    continue;
                }

                ParseObjectAttribute(obj, attribute);
            }

            ParseObjectContent(obj, element, defaultProperty, initializeFromTextValueInsteadOfConstructor);

            if (iSupportInitializeInstance != null)
            {
                iSupportInitializeInstance.EndInit();
            }

            currentXmlSpace   = oldXmlSpace;
            currentXamlObject = parentXamlObject;

            return(obj);
        }
예제 #19
0
        void ParseObjectContent(XamlObject obj, XmlElement element, XamlPropertyInfo defaultProperty,
                                XamlTextValue initializeFromTextValueInsteadOfConstructor)
        {
            bool isDefaultValueSet = false;

            XamlProperty collectionProperty        = null;
            object       collectionInstance        = null;
            Type         collectionType            = null;
            XmlElement   collectionPropertyElement = null;
            var          elementChildNodes         = GetNormalizedChildNodes(element);

            if (defaultProperty == null && obj.Instance != null &&
                CollectionSupport.IsCollectionType(obj.Instance.GetType()))
            {
                XamlObject       parentObj     = obj.ParentObject;
                var              parentElement = element.ParentNode;
                XamlPropertyInfo propertyInfo;
                if (parentObj != null)
                {
                    propertyInfo = GetPropertyInfo(settings.TypeFinder, parentObj.Instance, parentObj.ElementType,
                                                   parentElement.NamespaceURI, parentElement.LocalName);
                    collectionProperty = FindExistingXamlProperty(parentObj, propertyInfo);
                }
                collectionInstance        = obj.Instance;
                collectionType            = obj.ElementType;
                collectionPropertyElement = element;
            }
            else if (defaultProperty != null && defaultProperty.IsCollection && !element.IsEmpty)
            {
                foreach (XmlNode childNode in elementChildNodes)
                {
                    currentParsedNode = childNode;
                    XmlElement childElement = childNode as XmlElement;
                    if (childElement == null || !ObjectChildElementIsPropertyElement(childElement))
                    {
                        obj.AddProperty(collectionProperty = new XamlProperty(obj, defaultProperty));
                        collectionType     = defaultProperty.ReturnType;
                        collectionInstance = defaultProperty.GetValue(obj.Instance);
                        break;
                    }
                }
            }

            currentParsedNode = element;

            if (collectionType != null && collectionInstance == null && elementChildNodes.Count() == 1)
            {
                var firstChild = elementChildNodes.First() as XmlElement;
                if (ObjectChildElementIsCollectionInstance(firstChild, collectionType))
                {
                    collectionInstance = ParseObject(firstChild);
                    collectionProperty.PropertyValue = (XamlPropertyValue)collectionInstance;
                }
                else
                {
                    throw new XamlLoadException("Collection Instance is null");
                }
            }
            else
            {
                foreach (XmlNode childNode in elementChildNodes)
                {
                    currentParsedNode = childNode;
                    XmlElement childElement = childNode as XmlElement;
                    if (childElement != null)
                    {
                        if (childElement.NamespaceURI == XamlConstants.XamlNamespace)
                        {
                            continue;
                        }

                        if (ObjectChildElementIsPropertyElement(childElement))
                        {
                            ParseObjectChildElementAsPropertyElement(obj, childElement, defaultProperty);
                            continue;
                        }
                    }
                    if (initializeFromTextValueInsteadOfConstructor != null)
                    {
                        continue;
                    }
                    XamlPropertyValue childValue = ParseValue(childNode);
                    if (childValue != null)
                    {
                        if (collectionProperty != null)
                        {
                            collectionProperty.ParserAddCollectionElement(collectionPropertyElement, childValue);
                            CollectionSupport.AddToCollection(collectionType, collectionInstance, childValue);
                        }
                        else if (collectionProperty == null && collectionInstance is ResourceDictionary)
                        {
                            CollectionSupport.AddToCollection(collectionType, collectionInstance, childValue);
                        }
                        else
                        {
                            if (defaultProperty == null)
                            {
                                throw new XamlLoadException(
                                          "This element does not have a default value, cannot assign to it");
                            }

                            if (isDefaultValueSet)
                            {
                                throw new XamlLoadException("default property may have only one value assigned");
                            }

                            obj.AddProperty(new XamlProperty(obj, defaultProperty, childValue));
                            isDefaultValueSet = true;
                        }
                    }
                }
            }

            currentParsedNode = element;
        }