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)); } }
/// <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); }
internal static object CreateObjectFromAttributeText(string valueText, XamlPropertyInfo targetProperty, XamlObject scope) { try { 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())); } if (targetProperty.ReturnType == typeof(Brush)) { return(new BrushConverter().ConvertFromString(valueText) as SolidColorBrush); } return(targetProperty.TypeConverter.ConvertFromString( scope.OwnerDocument.GetTypeDescriptorContext(scope), CultureInfo.InvariantCulture, valueText)); } catch (Exception e) { IXamlErrorSink sink = (IXamlErrorSink)scope.OwnerDocument.ServiceProvider.GetService(typeof(IXamlErrorSink)); if (sink != null) { sink.ReportError(e.Message + " in property: " + targetProperty.FullyQualifiedName, 0, 0); } } return(null); }
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)); } }
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); }
void ParseObjectContent(XamlObject obj, XmlElement element, XamlPropertyInfo defaultProperty, XamlTextValue initializeFromTextValueInsteadOfConstructor) { bool isDefaultValueSet = false; object defaultPropertyValue = null; XamlProperty defaultCollectionProperty = null; if (defaultProperty != null && defaultProperty.IsCollection && !element.IsEmpty) { defaultPropertyValue = defaultProperty.GetValue(obj.Instance); obj.AddProperty(defaultCollectionProperty = new XamlProperty(obj, defaultProperty)); } foreach (XmlNode childNode in GetNormalizedChildNodes(element)) { XmlElement childElement = childNode as XmlElement; if (childElement != null) { if (childElement.NamespaceURI == XamlConstants.XamlNamespace) { continue; } if (ObjectChildElementIsPropertyElement(childElement)) { ParseObjectChildElementAsPropertyElement(obj, childElement, defaultProperty, defaultPropertyValue); continue; } } if (initializeFromTextValueInsteadOfConstructor != null) { continue; } XamlPropertyValue childValue = ParseValue(childNode); if (childValue != null) { if (defaultProperty != null && defaultProperty.IsCollection) { defaultCollectionProperty.ParserAddCollectionElement(null, childValue); CollectionSupport.AddToCollection(defaultProperty.ReturnType, defaultPropertyValue, 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; } } } }
internal XamlProperty(XamlObject parentObject, XamlPropertyInfo propertyInfo) { this.parentObject = parentObject; this.propertyInfo = propertyInfo; if (propertyInfo.IsCollection) { isCollection = true; collectionElements = new CollectionElementsCollection(this); } }
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; } }
// 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(); }
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."); }
protected override void InsertItem(int index, XamlPropertyValue item) { XamlPropertyInfo info = property.propertyInfo; object collection = info.GetValue(property.ParentObject.Instance); CollectionSupport.Insert(info.ReturnType, collection, item, index); item.ParentProperty = property; property.InsertNodeInCollection(item.GetNodeForCollection(), index); base.InsertItem(index, item); }
static XamlPropertyInfo FindAttachedProperty(Type elementType, string propertyName) { XamlPropertyInfo pi = TryFindAttachedProperty(elementType, propertyName); if (pi != null) { return(pi); } else { throw new XamlLoadException("attached property " + elementType.Name + "." + propertyName + " not found"); } }
protected override void RemoveItem(int index) { XamlPropertyInfo info = property.propertyInfo; object collection = info.GetValue(property.ParentObject.Instance); if (!CollectionSupport.RemoveItemAt(info.ReturnType, collection, index)) { CollectionSupport.RemoveItem(info.ReturnType, collection, this[index].GetValueFor(info)); } this[index].RemoveNodeFromParent(); this[index].ParentProperty = null; base.RemoveItem(index); }
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)); }
internal XamlProperty(XamlObject parentObject, XamlPropertyInfo propertyInfo) { this.parentObject = parentObject; this.propertyInfo = propertyInfo; if (propertyInfo.IsCollection) { isCollection = true; collectionElements = new CollectionElementsCollection(this); if (propertyInfo.Name.Equals(XamlConstants.ResourcesPropertyName, StringComparison.Ordinal) && propertyInfo.ReturnType == typeof(ResourceDictionary)) { isResources = true; } } }
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)); }
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); } }
internal static XamlPropertyInfo FindProperty(object elementInstance, Type propertyType, string propertyName) { PropertyDescriptorCollection properties; if (elementInstance != null) { properties = TypeDescriptor.GetProperties(elementInstance); } else { properties = TypeDescriptor.GetProperties(propertyType); } PropertyDescriptor propertyInfo = properties[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"); }
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)); } }
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"); }
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)); } }
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 = 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) { 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; } } } foreach (XmlNode childNode in elementChildNodes) { 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 (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; } } } }
XamlObject ParseObject(XmlElement element) { Type elementType = settings.TypeFinder.GetType(element.NamespaceURI, element.LocalName); 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 (onlyTextNodes && numberOfTextNodes == 1) { foreach (XmlNode childNode in element.ChildNodes) { if (childNode.NodeType == XmlNodeType.Text) { initializeFromTextValueInsteadOfConstructor = (XamlTextValue)ParseValue(childNode); } } } } 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) { if (attribute.LocalName == "Name") { try { NameScopeHelper.NameChanged(obj, null, attribute.Value); } catch (Exception x) { ReportException(x, attribute); } } continue; } ParseObjectAttribute(obj, attribute); } if (!(obj.Instance is Style)) { ParseObjectContent(obj, element, defaultProperty, initializeFromTextValueInsteadOfConstructor); } if (iSupportInitializeInstance != null) { iSupportInitializeInstance.EndInit(); } currentXmlSpace = oldXmlSpace; currentXamlObject = parentXamlObject; return(obj); }
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))); }
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 (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; }
void ParseObjectContent(XamlObject obj, XmlElement element, XamlPropertyInfo defaultProperty, XamlTextValue initializeFromTextValueInsteadOfConstructor) { XamlPropertyValue setDefaultValueTo = null; object defaultPropertyValue = null; XamlProperty defaultCollectionProperty = null; if (defaultProperty != null && defaultProperty.IsCollection && !element.IsEmpty) { defaultPropertyValue = defaultProperty.GetValue(obj.Instance); obj.AddProperty(defaultCollectionProperty = new XamlProperty(obj, defaultProperty)); } foreach (XmlNode childNode in GetNormalizedChildNodes(element)) { // I don't know why the official XamlReader runs the property getter // here, but let's try to imitate it as good as possible if (defaultProperty != null && !defaultProperty.IsCollection) { for (; combinedNormalizedChildNodes > 0; combinedNormalizedChildNodes--) { defaultProperty.GetValue(obj.Instance); } } XmlElement childElement = childNode as XmlElement; if (childElement != null) { if (childElement.NamespaceURI == XamlConstants.XamlNamespace) { continue; } if (ObjectChildElementIsPropertyElement(childElement)) { // I don't know why the official XamlReader runs the property getter // here, but let's try to imitate it as good as possible if (defaultProperty != null && !defaultProperty.IsCollection) { defaultProperty.GetValue(obj.Instance); } ParseObjectChildElementAsPropertyElement(obj, childElement, defaultProperty, defaultPropertyValue); continue; } } if (initializeFromTextValueInsteadOfConstructor != null) { continue; } XamlPropertyValue childValue = ParseValue(childNode); if (childValue != null) { if (defaultProperty != null && defaultProperty.IsCollection) { defaultCollectionProperty.ParserAddCollectionElement(null, childValue); CollectionSupport.AddToCollection(defaultProperty.ReturnType, defaultPropertyValue, childValue); } else { if (setDefaultValueTo != null) { throw new XamlLoadException("default property may have only one value assigned"); } setDefaultValueTo = childValue; } } } if (defaultProperty != null && !defaultProperty.IsCollection && !element.IsEmpty) { // Runs even when defaultValueSet==false! // Again, no idea why the official XamlReader does this. defaultProperty.GetValue(obj.Instance); } if (setDefaultValueTo != null) { if (defaultProperty == null) { throw new XamlLoadException("This element does not have a default value, cannot assign to it"); } obj.AddProperty(new XamlProperty(obj, defaultProperty, setDefaultValueTo)); } }
/// <summary> /// used internally by the XamlParser. /// </summary> internal abstract object GetValueFor(XamlPropertyInfo targetProperty);
static bool IsElementChildACollectionForProperty(XamlTypeFinder typeFinder, XmlElement element, XamlPropertyInfo propertyInfo) { return element.ChildNodes.Count == 1 && propertyInfo.ReturnType.IsAssignableFrom(FindType(typeFinder, element.FirstChild.NamespaceURI, element.FirstChild.LocalName)); }
internal static object CreateObjectFromAttributeText(string valueText, XamlPropertyInfo targetProperty, XamlObject scope) { return targetProperty.TypeConverter.ConvertFromString( scope.OwnerDocument.GetTypeDescriptorContext(scope), CultureInfo.InvariantCulture, valueText); }
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."); }
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); }
static bool IsElementChildACollectionForProperty(XamlTypeFinder typeFinder, XmlElement element, XamlPropertyInfo propertyInfo) { return(element.ChildNodes.Count == 1 && propertyInfo.ReturnType.IsAssignableFrom(FindType(typeFinder, element.FirstChild.NamespaceURI, element.FirstChild.LocalName))); }
internal static object CreateObjectFromAttributeText(string valueText, XamlPropertyInfo targetProperty, XamlObject scope) { return(targetProperty.TypeConverter.ConvertFromString( scope.OwnerDocument.GetTypeDescriptorContext(scope), CultureInfo.InvariantCulture, valueText)); }
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)); }
void ParseObjectContent(XamlObject obj, XmlElement element, XamlPropertyInfo defaultProperty, XamlTextValue initializeFromTextValueInsteadOfConstructor) { XamlPropertyValue setDefaultValueTo = null; object defaultPropertyValue = null; XamlProperty defaultCollectionProperty = null; if (defaultProperty != null && defaultProperty.IsCollection && !element.IsEmpty) { defaultPropertyValue = defaultProperty.GetValue(obj.Instance); obj.AddProperty(defaultCollectionProperty = new XamlProperty(obj, defaultProperty)); } foreach (XmlNode childNode in GetNormalizedChildNodes(element)) { // I don't know why the official XamlReader runs the property getter // here, but let's try to imitate it as good as possible if (defaultProperty != null && !defaultProperty.IsCollection) { for (; combinedNormalizedChildNodes > 0; combinedNormalizedChildNodes--) { defaultProperty.GetValue(obj.Instance); } } XmlElement childElement = childNode as XmlElement; if (childElement != null) { if (childElement.NamespaceURI == XamlConstants.XamlNamespace) continue; if (ObjectChildElementIsPropertyElement(childElement)) { // I don't know why the official XamlReader runs the property getter // here, but let's try to imitate it as good as possible if (defaultProperty != null && !defaultProperty.IsCollection) { defaultProperty.GetValue(obj.Instance); } ParseObjectChildElementAsPropertyElement(obj, childElement, defaultProperty, defaultPropertyValue); continue; } } if (initializeFromTextValueInsteadOfConstructor != null) continue; XamlPropertyValue childValue = ParseValue(childNode); if (childValue != null) { if (defaultProperty != null && defaultProperty.IsCollection) { defaultCollectionProperty.ParserAddCollectionElement(null, childValue); CollectionSupport.AddToCollection(defaultProperty.ReturnType, defaultPropertyValue, childValue); } else { if (setDefaultValueTo != null) throw new XamlLoadException("default property may have only one value assigned"); setDefaultValueTo = childValue; } } } if (defaultProperty != null && !defaultProperty.IsCollection && !element.IsEmpty) { // Runs even when defaultValueSet==false! // Again, no idea why the official XamlReader does this. defaultProperty.GetValue(obj.Instance); } if (setDefaultValueTo != null) { if (defaultProperty == null) { throw new XamlLoadException("This element does not have a default value, cannot assign to it"); } obj.AddProperty(new XamlProperty(obj, defaultProperty, setDefaultValueTo)); } }
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.FirstChild); } else { collectionInstance = collectionProperty.propertyInfo.GetValue(obj.Instance); collectionProperty.ParserSetPropertyElement(element); } } 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) { 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); } } } currentXmlSpace = oldXmlSpace; }
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; }
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); }
void ParseObjectContent(XamlObject obj, XmlElement element, XamlPropertyInfo defaultProperty, XamlTextValue initializeFromTextValueInsteadOfConstructor) { bool isDefaultValueSet = false; object defaultPropertyValue = null; XamlProperty defaultCollectionProperty = null; if (defaultProperty != null && defaultProperty.IsCollection && !element.IsEmpty) { defaultPropertyValue = defaultProperty.GetValue(obj.Instance); obj.AddProperty(defaultCollectionProperty = new XamlProperty(obj, defaultProperty)); } foreach (XmlNode childNode in GetNormalizedChildNodes(element)) { XmlElement childElement = childNode as XmlElement; if (childElement != null) { if (childElement.NamespaceURI == XamlConstants.XamlNamespace) continue; if (ObjectChildElementIsPropertyElement(childElement)) { ParseObjectChildElementAsPropertyElement(obj, childElement, defaultProperty, defaultPropertyValue); continue; } } if (initializeFromTextValueInsteadOfConstructor != null) continue; XamlPropertyValue childValue = ParseValue(childNode); if (childValue != null) { if (defaultProperty != null && defaultProperty.IsCollection) { defaultCollectionProperty.ParserAddCollectionElement(null, childValue); CollectionSupport.AddToCollection(defaultProperty.ReturnType, defaultPropertyValue, 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; } } } }