/// <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)); } }
/// <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)); } }