public void AssignValue(IDataDescriptor dd, object value) { if (dd.SupportsWrite && (value == null || dd.DataType.IsAssignableFrom(value.GetType()))) { dd.Value = value; } else if (ReflectionHelper.CheckHandleCollectionAssignment(dd.Value, value)) { } else { dd.Value = Convert(value, dd.DataType); } }
/// <summary> /// Instantiates the specified XML element located under the current element context /// in the <see cref="_elementContextStack"/> and sets the resulting element up. /// </summary> /// <remarks> /// Before calling this, the parent element, which is the current top element /// on the element context stack, has to be instantiated and its namespaces /// have to be imported. In the current implementation, its attributes will /// also already be processed. /// When this method returns, the returned visual element is completely set up, /// this means, it was instantiated, its members and events were processed /// and its content member was assigned. The processing of the complete /// structure under <paramref name="currentElement"/> has finished. /// </remarks> /// <param name="currentElement">The XML element under the /// current element on the element's context stack, which has to be /// instantiated and set up.</param> /// <param name="key">Will be set if an <c>x:Key</c> attribute was set on the /// element to parse.</param> /// <returns>Instantiated XAML visual element corresponding to the /// specified <paramref name="currentElement"/>.</returns> protected object Instantiate(XmlElement currentElement, out object key) { ElementContextInfo elementContext = _elementContextStack.PushElementContext(currentElement); try { string name = null; key = null; IList <XmlAttribute> remainingAttributes = new List <XmlAttribute>(currentElement.Attributes.Count); // Step 1: Process namespace declarations (to be done first) foreach (XmlAttribute attr in currentElement.Attributes) { // We have to sort out namespace declarations. // For both declarations xmlns="..." and xmlns:xx="...", the parser returns the // namespace URI "http://www.w3.org/2000/xmlns/" (static constant // <see cref="XMLNS_NS_URI"/>) for the attribute, so we check for this // namespace URI. The value of the attribute (for example // "http://schemas.microsoft.com/winfx/2006/xaml") is the URI // of the namespace to be imported. if (attr.NamespaceURI == XMLNS_NS_URI) { string importNamespaceURI = attr.Value; INamespaceHandler handler; if (importNamespaceURI == XamlNamespaceHandler.XAML_NS_URI) { // Implicit namespace: Use default x:-handler handler = new XamlNamespaceHandler(); } else if (importNamespaceURI.StartsWith("clr-namespace:")) { handler = ImportClrNamespace(importNamespaceURI); } else { handler = _importCustomNamespace(this, importNamespaceURI); } _elementContextStack.RegisterNamespaceHandler(importNamespaceURI, handler); } else { // Store other attributes so we don't need to sort out the namespace declarations in step 3 remainingAttributes.Add(attr); } } // Step 2: Instantiate the element elementContext.Instance = GetNamespaceHandler(currentElement.NamespaceURI). InstantiateElement(this, currentElement.LocalName, new List <object>()); IInitializable initializable = elementContext.Instance as IInitializable; if (initializable != null) { initializable.StartInitialization(this); } // Step 3: Name registration and check for x:Key (to be done before child objects are built) foreach (XmlAttribute attr in remainingAttributes) { CheckNameOrKey(attr, ref name, ref key); } foreach (XmlNode node in currentElement.ChildNodes) { CheckNameOrKey(node, ref name, ref key); } if (name != null) { RegisterName(name, elementContext.Instance); } // Step 4: Members and events in attribute syntax foreach (XmlAttribute attr in remainingAttributes) { HandleMemberOrEventAssignment(attr); } // Step 5: Member values in member element syntax foreach (XmlNode node in currentElement.ChildNodes) { // Hint: We do not enforce, that object elements, which are used to fill the // XAML content member within an object element, must be contiguous if (node is XmlElement && node.LocalName.IndexOf('.') != -1) // "." is used as indicator that we have a member declaration { // Check XML attributes on member element - only x:Uid is permitted foreach (XmlAttribute attr in node.Attributes) { if (attr.NamespaceURI != XamlNamespaceHandler.XAML_NS_URI || attr.LocalName != "Uid") { throw new XamlParserException("No attributes are allowed on member elements except x:Uid"); } // TODO: Handle x:Uid markup extension } HandleMemberOrEventAssignment(node); } } // Step 6: Handle child elements if (elementContext.Instance is INativeXamlObject) { // Implementors of INativeXamlObject will handle their XAML child elements theirselves ((INativeXamlObject)elementContext.Instance).HandleChildren(this, currentElement); } else { // Content member value/Children handled by this XAML parser object value = ParseValue(currentElement); if (value != null) { IDataDescriptor dd; if (elementContext.Instance is IContentEnabled && ((IContentEnabled)elementContext.Instance).FindContentProperty(out dd)) { HandleMemberAssignment(dd, value); } else if (ReflectionHelper.CheckHandleCollectionAssignment(elementContext.Instance, value)) { } else { throw new XamlBindingException("Visual element '{0}' doesn't support adding children", currentElement.Name); } } } // Step 7: Initialize if (initializable != null) { initializable.FinishInitialization(this); } return(elementContext.Instance); } finally { _elementContextStack.PopElementContext(); } }