/// <summary>
        /// Processes the element which contains property value.
        /// </summary>
        private IAbstractPropertySetter ProcessElementProperty(IAbstractControl control, IPropertyDescriptor property, IEnumerable <DothtmlNode> elementContent, DothtmlElementNode propertyWrapperElement)
        {
            // resolve data context
            var dataContext = control.DataContextTypeStack;

            dataContext = GetDataContextChange(dataContext, control, property);

            // the element is a property
            if (IsTemplateProperty(property))
            {
                // template
                return(treeBuilder.BuildPropertyTemplate(property, ProcessTemplate(control, elementContent, dataContext), propertyWrapperElement));
            }
            else if (IsCollectionProperty(property))
            {
                var collectionType = GetCollectionType(property);
                // collection of elements
                var collection =
                    FilterNodes <DothtmlElementNode>(elementContent, property)
                    .Select(childObject => ProcessObjectElement(childObject, dataContext));
                if (collectionType != null)
                {
                    collection = FilterOrError(collection,
                                               c => c.Metadata.Type.IsAssignableTo(collectionType),
                                               c => c.DothtmlNode.AddError($"Control type {c.Metadata.Type.FullName} can't be used in collection of type {collectionType.FullName}."));
                }

                return(treeBuilder.BuildPropertyControlCollection(property, collection.ToArray(), propertyWrapperElement));
            }
            else if (property.PropertyType.IsEqualTo(new ResolvedTypeDescriptor(typeof(string))))
            {
                // string property
                var strings = FilterNodes <DothtmlLiteralNode>(elementContent, property);
                var value   = string.Concat(strings.Select(s => s.Value));
                return(treeBuilder.BuildPropertyValue(property, value, propertyWrapperElement));
            }
            else if (IsControlProperty(property))
            {
                // new object
                var children = FilterNodes <DothtmlElementNode>(elementContent, property).ToList();
                if (children.Count > 1)
                {
                    foreach (var c in children.Skip(1))
                    {
                        c.AddError($"The property '{property.MarkupOptions.Name}' can have only one child element!");
                    }
                    children = children.Take(1).ToList();
                }
                if (children.Count == 1)
                {
                    return(treeBuilder.BuildPropertyControl(property, ProcessObjectElement(children[0], dataContext), propertyWrapperElement));
                }
                else
                {
                    return(treeBuilder.BuildPropertyControl(property, null, propertyWrapperElement));
                }
            }
            else
            {
                control.DothtmlNode.AddError($"The property '{property.FullName}' is not supported!");
                return(treeBuilder.BuildPropertyValue(property, null, propertyWrapperElement));
            }
        }
Example #2
0
        /// <summary>
        /// Processes the element which contains property value.
        /// </summary>
        private IAbstractPropertySetter ProcessElementProperty(IAbstractControl control, IPropertyDescriptor property, IEnumerable <DothtmlNode> elementContent, DothtmlElementNode propertyWrapperElement)
        {
            IEnumerable <IAbstractControl> filterByType(ITypeDescriptor type, IEnumerable <IAbstractControl> controls) =>
            FilterOrError(controls,
                          c => c.Metadata.Type.IsAssignableTo(type),
                          c => {
                // empty nodes are only filtered, non-empty nodes cause errors
                if (c.DothtmlNode.IsNotEmpty())
                {
                    c.DothtmlNode.AddError($"Control type {c.Metadata.Type.FullName} can't be used in collection of type {type.FullName}.");
                }
            });

            // resolve data context
            var dataContext = control.DataContextTypeStack;

            dataContext = GetDataContextChange(dataContext, control, property);

            // the element is a property
            if (IsTemplateProperty(property))
            {
                // template
                return(treeBuilder.BuildPropertyTemplate(property, ProcessTemplate(control, elementContent, dataContext), propertyWrapperElement));
            }
            else if (IsCollectionProperty(property))
            {
                var collectionType = GetCollectionType(property);
                // collection of elements
                var collection = elementContent.Select(childObject => ProcessNode(control, childObject, control.Metadata, dataContext));
                if (collectionType != null)
                {
                    collection = filterByType(collectionType, collection);
                }

                return(treeBuilder.BuildPropertyControlCollection(property, collection.ToArray(), propertyWrapperElement));
            }
            else if (property.PropertyType.IsEqualTo(new ResolvedTypeDescriptor(typeof(string))))
            {
                // string property
                var strings = FilterNodes <DothtmlLiteralNode>(elementContent, property);
                var value   = string.Concat(strings.Select(s => s.Value));
                return(treeBuilder.BuildPropertyValue(property, value, propertyWrapperElement));
            }
            else if (IsControlProperty(property))
            {
                var children = filterByType(property.PropertyType, elementContent.Select(childObject => ProcessNode(control, childObject, control.Metadata, dataContext))).ToArray();
                if (children.Length > 1)
                {
                    // try with the empty nodes are excluded
                    children = children.Where(c => c.DothtmlNode.IsNotEmpty()).ToArray();
                    if (children.Length > 1)
                    {
                        foreach (var c in children.Skip(1))
                        {
                            c.DothtmlNode.AddError($"The property '{property.MarkupOptions.Name}' can have only one child element!");
                        }
                    }
                }
                if (children.Length >= 1)
                {
                    return(treeBuilder.BuildPropertyControl(property, children[0], propertyWrapperElement));
                }
                else
                {
                    return(treeBuilder.BuildPropertyControl(property, null, propertyWrapperElement));
                }
            }
            else
            {
                control.DothtmlNode.AddError($"The property '{property.FullName}' is not supported!");
                return(treeBuilder.BuildPropertyValue(property, null, propertyWrapperElement));
            }
        }