Ejemplo n.º 1
0
 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);
     }
 }
Ejemplo n.º 2
0
        /// <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();
            }
        }