private static void AppendPropertyValue(StringBuilder sb, XamlPropertyValue value, bool isStringProperty)
        {
            var textValue = value as XamlTextValue;

            if (textValue != null)
            {
                string text          = textValue.Text;
                bool   containsSpace = text.Contains(' ');

                if (containsSpace)
                {
                    sb.Append('\'');
                }

                if (isStringProperty)
                {
                    sb.Append(text.Replace("\\", "\\\\").Replace("{", "\\{").Replace("}", "\\}"));
                }
                else
                {
                    sb.Append(text.Replace("\\", "\\\\"));
                }

                if (containsSpace)
                {
                    sb.Append('\'');
                }
            }
            else if (value is XamlObject)
            {
                sb.Append(Print(value as XamlObject));
            }
        }
Beispiel #2
0
        void PossiblyNameChanged(XamlPropertyValue oldValue, XamlPropertyValue newValue)
        {
            if (ParentObject.RuntimeNameProperty != null && PropertyName == ParentObject.RuntimeNameProperty)
            {
                if (!String.IsNullOrEmpty(ParentObject.GetXamlAttribute("Name")))
                {
                    throw new XamlLoadException("The property 'Name' is set more than once.");
                }

                string oldName = null;
                string newName = null;

                var oldTextValue = oldValue as XamlTextValue;
                if (oldTextValue != null)
                {
                    oldName = oldTextValue.Text;
                }

                var newTextValue = newValue as XamlTextValue;
                if (newTextValue != null)
                {
                    newName = newTextValue.Text;
                }

                NameScopeHelper.NameChanged(ParentObject, oldName, newName);
            }
        }
Beispiel #3
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);
        }
Beispiel #4
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();
        }
Beispiel #5
0
        /// <summary>
        /// Removes an item instance from the specified collection.
        /// </summary>
        internal static void RemoveItem(Type collectionType, object collectionInstance, object item,
                                        XamlPropertyValue element)
        {
            var dictionary = collectionInstance as IDictionary;
            var xamlObject = element as XamlObject;

            if (dictionary != null && xamlObject != null)
            {
                dictionary.Remove(xamlObject.GetXamlAttribute("Key"));
            }
            else
            {
                RemoveItem(collectionType, collectionInstance, item);
            }
        }
Beispiel #6
0
        void SetPropertyValue(XamlPropertyValue value)
        {
            // Binding...
            //if (IsCollection) {
            //    throw new InvalidOperationException("Cannot set the value of collection properties.");
            //}

            bool wasSet = this.IsSet;

            PossiblyNameChanged(propertyValue, value);

            //reset expression
            var xamlObject = propertyValue as XamlObject;

            if (xamlObject != null && xamlObject.IsMarkupExtension)
            {
                propertyInfo.ResetValue(parentObject.Instance);
            }

            ResetInternal();

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

            ParentObject.OnPropertyChanged(this);

            if (!wasSet)
            {
                if (IsSetChanged != null)
                {
                    IsSetChanged(this, EventArgs.Empty);
                }
            }

            if (ValueChanged != null)
            {
                ValueChanged(this, EventArgs.Empty);
            }
        }
Beispiel #7
0
        /// <summary>
        /// Adds a value at the specified index in the collection.
        /// </summary>
        public static bool Insert(Type collectionType, object collectionInstance, XamlPropertyValue newElement,
                                  int index)
        {
            object value = newElement.GetValueFor(null);

            // Using IList, with possible Add instead of Insert, was primarily added as a workaround
            // for a peculiarity (or bug) with collections inside System.Windows.Input namespace.
            // See CollectionTests.InputCollectionsPeculiarityOrBug test method for details.
            var list = collectionInstance as IList;

            if (list != null)
            {
                if (list.Count == index)
                {
                    list.Add(value);
                }
                else
                {
                    list.Insert(index, value);
                }
                return(true);
            }
            else
            {
                var hasInsert = collectionType.GetMethods().Any(x => x.Name == "Insert");

                if (hasInsert)
                {
                    collectionType.InvokeMember(
                        "Insert", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance,
                        null, collectionInstance,
                        new object[] { index, value },
                        CultureInfo.InvariantCulture);

                    return(true);
                }
            }

            return(false);
        }
Beispiel #8
0
        void ResetInternal()
        {
            bool isExplicitCollection = false;

            if (propertyValue != null)
            {
                isExplicitCollection = IsCollection;

                propertyValue.RemoveNodeFromParent();
                propertyValue.ParentProperty = null;
                propertyValue = null;
            }
            if (_propertyElement != null)
            {
                Debug.Assert(!isExplicitCollection || _propertyElement.ParentNode == null);

                if (!isExplicitCollection)
                {
                    _propertyElement.ParentNode.RemoveChild(_propertyElement);
                }
                _propertyElement = null;
            }
        }
Beispiel #9
0
 /// <summary>
 /// used internally by the XamlParser.
 /// Add a collection element that already is part of the XML DOM.
 /// </summary>
 internal void ParserAddCollectionElement(XmlElement collectionPropertyElement, XamlPropertyValue val)
 {
     if (collectionPropertyElement != null && _propertyElement == null)
     {
         ParserSetPropertyElement(collectionPropertyElement);
     }
     collectionElements.AddInternal(val);
     val.ParentProperty = this;
     if (collectionPropertyElement != _propertyElement)
     {
         val.RemoveNodeFromParent();
         val.AddNodeTo(this);
     }
 }
Beispiel #10
0
        /// <summary>
        /// Adds a value to the end of a collection.
        /// </summary>
        public static void AddToCollection(Type collectionType, object collectionInstance, XamlPropertyValue newElement)
        {
            IAddChild addChild = collectionInstance as IAddChild;

            if (addChild != null)
            {
                if (newElement is XamlTextValue)
                {
                    addChild.AddText((string)newElement.GetValueFor(null));
                }
                else
                {
                    addChild.AddChild(newElement.GetValueFor(null));
                }
            }
            else if (collectionInstance is IDictionary)
            {
                object val = newElement.GetValueFor(null);
                object key = newElement is XamlObject ? ((XamlObject)newElement).GetXamlAttribute("Key") : null;
                if (key == null || (key as string) == "")
                {
                    if (val is Style)
                    {
                        key = ((Style)val).TargetType;
                    }
                }
                if (key == null || (key as string) == "")
                {
                    key = val;
                }
                ((IDictionary)collectionInstance).Add(key, val);
            }
            else
            {
                collectionType.InvokeMember(
                    "Add", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance,
                    null, collectionInstance,
                    new object[] { newElement.GetValueFor(null) },
                    CultureInfo.InvariantCulture);
            }
        }
Beispiel #11
0
 /// <summary>
 /// Adds a value at the specified index in the collection. A return value indicates whether the Insert succeeded.
 /// </summary>
 /// <returns>True if the Insert succeeded, false if the collection type does not support Insert.</returns>
 internal static bool TryInsert(Type collectionType, object collectionInstance, XamlPropertyValue newElement,
                                int index)
 {
     try
     {
         return(Insert(collectionType, collectionInstance, newElement, index));
     }
     catch (MissingMethodException)
     {
         return(false);
     }
 }
Beispiel #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;
        }
Beispiel #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;
        }