/// <summary> /// Parses the contents of an <see cref="XmlNode"/> (not the node itself!). /// Parsed will be instances of <see cref="XmlAttribute"/> and <see cref="XmlElement"/>. /// In case the node is an <see cref="XmlAttribute"/>, its value will be parsed /// and returned. This will normally be a string or an instance of a /// markup extension. In case the node is an <see cref="XmlElement"/>, /// its children will be instantiatedan returned as an <see cref="IList"/> or /// an <see cref="IDictionary"/>, depending on whether the elements have a /// <c>x:Key</c> attribute associated. /// </summary> /// <param name="node">The XML node, an <see cref="XmlAttribute"/> or /// an <see cref="XmlElement"/>, whose contents should be parsed.</param> /// <returns>Parsed value. This is either a string, a markup extension /// instance, an <c>IList<object></c> or an <c>IDictionary<object, object></c>.</returns> protected object ParseValue(XmlNode node) { if (node is XmlAttribute) // Member attribute { return(ParseValue(node.Value)); } if (!(node is XmlElement)) { return(null); } // Handle explicit or implicit (Content) member element // Return value's type will be either a dict or a list, depending on contents IList <object> resultList = new List <object>(); IDictionary <object, object> resultDict = new Dictionary <object, object>(); foreach (XmlNode childNode in node.ChildNodes) { if (childNode is XmlElement) { if (childNode.LocalName.IndexOf('.') != -1) // "." is used as indicator that we have a member declaration // Ignore member assignments here - we focus on our real children { continue; } object key; object value = Instantiate((XmlElement)childNode, out key); if (key == null) { key = GetImplicitKey(value); } IEvaluableMarkupExtension evaluableMarkupExtension = value as IEvaluableMarkupExtension; // Handle the case if a markup extension was instantiated as a child if (evaluableMarkupExtension != null) { evaluableMarkupExtension.Initialize(this); if (!evaluableMarkupExtension.Evaluate(out value)) { throw new XamlParserException("Could not evaluate markup extension '{0}'", evaluableMarkupExtension); } } value = ParserHelper.UnwrapIncludesAndCleanup(value); if (key == null) { resultList.Add(value); } else { try { resultDict.Add(key, value); } catch (ArgumentException e) { throw new XamlParserException("Duplicate key '{0}'", e, key); } } // If a key was provided, register the new element in the current context. // This is necessary if the new element should be accessed before all children // here created are added to their target collection. if (key != null) { _elementContextStack.CurrentElementContext.AddKeyedElement(key, value); } } else if (childNode is XmlText || childNode is XmlCDataSection) // Ignore other XmlCharacterData nodes { resultList.Add(((XmlCharacterData)childNode).Data); } } if (resultList.Count > 0 && resultDict.Count > 0) { throw new XamlBindingException( "Xaml parser parsing Element '{0}': Child elements containing x:Key attributes cannot be mixed with child elements without x:Key attribute", node.Name); } if (resultDict.Count > 0) { return(resultDict); } return(resultList.Count == 0 ? null : (resultList.Count == 1 ? resultList[0] : resultList)); }