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)); } }
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); } }
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); }
// 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(); }
/// <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); } }
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); } }
/// <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); }
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; } }
/// <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); } }
/// <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); } }
/// <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); } }
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; }
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; }