Example #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);
        }
Example #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);
        }
Example #3
0
        internal override void AddNodeTo(XamlProperty property)
        {
            XamlObject holder;

            if (!UpdateXmlAttribute(true, out holder))
            {
                property.AddChildNodeToProperty(element);
            }
            UpdateMarkupExtensionChain();
        }
Example #4
0
        /// <summary>
        /// Finds the specified property, or creates it if it doesn't exist.
        /// </summary>
        public XamlProperty FindOrCreateProperty(string propertyName)
        {
            if (propertyName == null)
            {
                throw new ArgumentNullException("propertyName");
            }

//			if (propertyName == ContentPropertyName)
//				return

            foreach (XamlProperty p in properties)
            {
                if (!p.IsAttached && p.PropertyName == propertyName)
                {
                    return(p);
                }
            }
            PropertyDescriptorCollection propertyDescriptors = TypeDescriptor.GetProperties(instance);
            PropertyDescriptor           propertyInfo        = propertyDescriptors[propertyName];
            XamlProperty newProperty;

            if (propertyInfo == null)
            {
                propertyDescriptors = TypeDescriptor.GetProperties(this.elementType);
                propertyInfo        = propertyDescriptors[propertyName];
            }

            if (propertyInfo != null)
            {
                newProperty = new XamlProperty(this, new XamlNormalPropertyInfo(propertyInfo));
            }
            else
            {
                EventDescriptorCollection events    = TypeDescriptor.GetEvents(instance);
                EventDescriptor           eventInfo = events[propertyName];

                if (eventInfo == null)
                {
                    events    = TypeDescriptor.GetEvents(this.elementType);
                    eventInfo = events[propertyName];
                }

                if (eventInfo != null)
                {
                    newProperty = new XamlProperty(this, new XamlEventPropertyInfo(eventInfo));
                }
                else
                {
                    throw new ArgumentException(
                              "The property '" + propertyName + "' doesn't exist on " + elementType.FullName, "propertyName");
                }
            }
            properties.Add(newProperty);
            return(newProperty);
        }
Example #5
0
        internal string GetPrefixForNamespace(string @namespace)
        {
            if (@namespace == XamlConstants.PresentationNamespace)
            {
                return(null);
            }

            string prefix = _xmlDoc.DocumentElement.GetPrefixOfNamespace(@namespace);

            if (_xmlDoc.DocumentElement.NamespaceURI == @namespace && _xmlDoc.Prefix == String.Empty)
            {
                return(string.Empty);
            }

            if (String.IsNullOrEmpty(prefix))
            {
                prefix = _typeFinder.GetPrefixForXmlNamespace(@namespace);

                string existingNamespaceForPrefix = null;
                if (!String.IsNullOrEmpty(prefix))
                {
                    existingNamespaceForPrefix = _xmlDoc.DocumentElement.GetNamespaceOfPrefix(prefix);
                }

                if (String.IsNullOrEmpty(prefix) ||
                    !String.IsNullOrEmpty(existingNamespaceForPrefix) &&
                    existingNamespaceForPrefix != @namespace)
                {
                    do
                    {
                        prefix = "Controls" + namespacePrefixCounter++;
                    } while (!String.IsNullOrEmpty(_xmlDoc.DocumentElement.GetNamespaceOfPrefix(prefix)));
                }

                string xmlnsPrefix = _xmlDoc.DocumentElement.GetPrefixOfNamespace(XamlConstants.XmlnsNamespace);
                System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(xmlnsPrefix));

                _xmlDoc.DocumentElement.SetAttribute(xmlnsPrefix + ":" + prefix, @namespace);

                if (@namespace == XamlConstants.DesignTimeNamespace)
                {
                    var ignorableProp = new XamlProperty(this._rootElement,
                                                         new XamlDependencyPropertyInfo(MarkupCompatibilityProperties.IgnorableProperty, true));
                    ignorableProp.SetAttribute(prefix);
                }
            }

            return(prefix);
        }
Example #6
0
        //TODO: reseting path property for binding doesn't work in XamlProperty
        //use CanResetValue()
        internal void OnPropertyChanged(XamlProperty property)
        {
            XamlObject holder;

            if (!UpdateXmlAttribute(false, out holder))
            {
                if (holder != null &&
                    holder.XmlAttribute != null)
                {
                    holder.XmlAttribute.OwnerElement.RemoveAttributeNode(holder.XmlAttribute);
                    holder.xmlAttribute = null;
                    holder.ParentProperty.AddChildNodeToProperty(holder.element);

                    bool isThisUpdated = false;
                    foreach (XamlObject propXamlObject in holder.Properties.Where((prop) => prop.IsSet)
                             .Select((prop) => prop.PropertyValue)
                             .OfType <XamlObject>())
                    {
                        XamlObject innerHolder;
                        bool       updateResult = propXamlObject.UpdateXmlAttribute(true, out innerHolder);
                        Debug.Assert(updateResult || innerHolder == null);

                        if (propXamlObject == this)
                        {
                            isThisUpdated = true;
                        }
                    }
                    if (!isThisUpdated)
                    {
                        this.UpdateXmlAttribute(true, out holder);
                    }
                }
            }
            UpdateMarkupExtensionChain();

            if (!element.HasChildNodes && !element.IsEmpty)
            {
                element.IsEmpty = true;
            }

            if (property == NameProperty)
            {
                if (NameChanged != null)
                {
                    NameChanged(this, EventArgs.Empty);
                }
            }
        }
Example #7
0
        /// <summary>For use by XamlParser only.</summary>
        internal void AddProperty(XamlProperty property)
        {
#if DEBUG
            if (property.IsAttached == false)
            {
                foreach (XamlProperty p in properties)
                {
                    if (p.IsAttached == false && p.PropertyName == property.PropertyName)
                    {
                        throw new XamlLoadException("duplicate property:" + property.PropertyName);
                    }
                }
            }
#endif
            properties.Add(property);
        }
Example #8
0
 internal override void AddNodeTo(XamlProperty property)
 {
     if (attribute != null)
     {
         property.ParentObject.XmlElement.Attributes.Append(attribute);
     }
     else if (textValue != null)
     {
         attribute = property.SetAttribute(textValue);
         textValue = null;
     }
     else if (cDataSection != null)
     {
         property.AddChildNodeToProperty(cDataSection);
     }
     else
     {
         property.AddChildNodeToProperty(textNode);
     }
 }
Example #9
0
        /// <summary>
        /// Sets an attribute in the x:-namespace.
        /// </summary>
        public void SetXamlAttribute(string name, string value)
        {
            XamlProperty runtimeNameProperty = null;
            bool         isNameChange        = false;

            if (name == "Name")
            {
                isNameChange = true;
                string oldName = GetXamlAttribute("Name");

                if (String.IsNullOrEmpty(oldName))
                {
                    runtimeNameProperty = this.NameProperty;
                    if (runtimeNameProperty != null)
                    {
                        if (runtimeNameProperty.IsSet)
                        {
                            oldName = (string)runtimeNameProperty.ValueOnInstance;
                        }
                        else
                        {
                            runtimeNameProperty = null;
                        }
                    }
                }

                if (String.IsNullOrEmpty(oldName))
                {
                    oldName = null;
                }

                NameScopeHelper.NameChanged(this, oldName, value);
            }

            if (value == null)
            {
                element.RemoveAttribute(name, XamlConstants.XamlNamespace);
            }
            else
            {
                var prefix     = element.GetPrefixOfNamespace(XamlConstants.XamlNamespace);
                var prefix2009 = element.GetPrefixOfNamespace(XamlConstants.Xaml2009Namespace);

                if (!string.IsNullOrEmpty(prefix))
                {
                    var attribute = element.OwnerDocument.CreateAttribute(prefix, name, XamlConstants.XamlNamespace);
                    attribute.InnerText = value;
                    element.SetAttributeNode(attribute);
                }
                else if (!string.IsNullOrEmpty(prefix2009))
                {
                    var attribute =
                        element.OwnerDocument.CreateAttribute(prefix, name, XamlConstants.Xaml2009Namespace);
                    attribute.InnerText = value;
                    element.SetAttributeNode(attribute);
                }
                else
                {
                    element.SetAttribute(name, XamlConstants.XamlNamespace, value);
                }
            }

            if (isNameChange)
            {
                bool nameChangedAlreadyRaised = false;
                if (runtimeNameProperty != null)
                {
                    var handler = new EventHandler((sender, e) => nameChangedAlreadyRaised = true);
                    this.NameChanged += handler;

                    try
                    {
                        runtimeNameProperty.Reset();
                    }
                    finally
                    {
                        this.NameChanged -= handler;
                    }
                }

                if (NameChanged != null && !nameChangedAlreadyRaised)
                {
                    NameChanged(this, EventArgs.Empty);
                }
            }
        }
Example #10
0
 internal abstract void AddNodeTo(XamlProperty property);
Example #11
0
        /// <summary>
        /// Create a XamlPropertyValue for the specified value instance.
        /// </summary>
        public XamlPropertyValue CreatePropertyValue(object instance, XamlProperty forProperty)
        {
            if (instance == null)
            {
                throw new ArgumentNullException("instance");
            }

            Type          elementType = instance.GetType();
            TypeConverter c           = TypeDescriptor.GetConverter(instance);
            var           ctx         = new DummyTypeDescriptorContext(this.ServiceProvider);

            ctx.Instance = instance;
            bool hasStringConverter = c.CanConvertTo(ctx, typeof(string)) && c.CanConvertFrom(typeof(string));

            if (forProperty != null && hasStringConverter)
            {
                if (instance is SolidColorBrush &&
                    _colorBrushDictionary.ContainsKey(((SolidColorBrush)instance).Color))
                {
                    var name = _colorBrushDictionary[((SolidColorBrush)instance).Color];
                    return(new XamlTextValue(this, name));
                }

                return(new XamlTextValue(this, c.ConvertToInvariantString(ctx, instance)));
            }

            string ns     = GetNamespaceFor(elementType);
            string prefix = GetPrefixForNamespace(ns);

            XmlElement xml = _xmlDoc.CreateElement(prefix, elementType.Name, ns);

            if (hasStringConverter && (XamlObject.GetContentPropertyName(elementType) != null ||
                                       IsNativeType(instance)))
            {
                xml.InnerText = c.ConvertToInvariantString(instance);
            }
            else if (instance is Brush && forProperty != null)
            {
                // TODO: this is a hacky fix, because Brush Editor doesn't
                // edit Design Items and so we have no XML, only the Brush
                // object and we need to parse the Brush to XAML!
                var s = new MemoryStream();
                XamlWriter.Save(instance, s);
                s.Seek(0, SeekOrigin.Begin);
                XmlDocument doc = new XmlDocument();
                doc.Load(s);
                xml = (XmlElement)_xmlDoc.ImportNode(doc.DocumentElement, true);

                var attLst = xml.Attributes.Cast <XmlAttribute>().ToList();
                foreach (XmlAttribute att in attLst)
                {
                    if (att.Name.StartsWith(XamlConstants.Xmlns))
                    {
                        var rootAtt = doc.DocumentElement.GetAttributeNode(att.Name);
                        if (rootAtt != null && rootAtt.Value == att.Value)
                        {
                            xml.Attributes.Remove(att);
                        }
                    }
                }
            }

            return(new XamlObject(this, xml, elementType, instance));
        }
Example #12
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;
        }
Example #13
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;
        }
 internal CollectionElementsCollection(XamlProperty property)
 {
     this.property = property;
 }