Browse Source

Fixed parser so it can handle explicit lists.

pull/77/head
gumme 12 years ago
parent
commit
b401bc5cc1
  1. 75
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs
  2. 36
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs

75
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs

@ -285,22 +285,41 @@ namespace ICSharpCode.WpfDesign.XamlDom
void ParseObjectContent(XamlObject obj, XmlElement element, XamlPropertyInfo defaultProperty, XamlTextValue initializeFromTextValueInsteadOfConstructor) void ParseObjectContent(XamlObject obj, XmlElement element, XamlPropertyInfo defaultProperty, XamlTextValue initializeFromTextValueInsteadOfConstructor)
{ {
bool isDefaultValueSet = false; bool isDefaultValueSet = false;
object defaultPropertyValue = null;
XamlProperty defaultCollectionProperty = null;
if (defaultProperty != null && defaultProperty.IsCollection && !element.IsEmpty) { XamlProperty collectionProperty = null;
defaultPropertyValue = defaultProperty.GetValue(obj.Instance); object collectionInstance = null;
obj.AddProperty(defaultCollectionProperty = new XamlProperty(obj, defaultProperty)); Type collectionType = null;
XmlElement collectionPropertyElement = null;
var elementChildNodes = GetNormalizedChildNodes(element);
if (defaultProperty == null && obj.Instance != null && CollectionSupport.IsCollectionType(obj.Instance.GetType())) {
XamlObject parentObj = obj.ParentObject;
var parentElement = element.ParentNode;
XamlPropertyInfo propertyInfo = GetPropertyInfo(settings.TypeFinder, parentObj.Instance, parentObj.ElementType, parentElement.NamespaceURI, parentElement.LocalName);
collectionProperty = FindExistingXamlProperty(parentObj, propertyInfo);
collectionInstance = obj.Instance;
collectionType = obj.ElementType;
collectionPropertyElement = element;
} else if (defaultProperty != null && defaultProperty.IsCollection && !element.IsEmpty) {
foreach (XmlNode childNode in elementChildNodes) {
XmlElement childElement = childNode as XmlElement;
if (childElement == null || !ObjectChildElementIsPropertyElement(childElement)) {
obj.AddProperty(collectionProperty = new XamlProperty(obj, defaultProperty));
collectionType = defaultProperty.ReturnType;
collectionInstance = defaultProperty.GetValue(obj.Instance);
break;
}
}
} }
foreach (XmlNode childNode in GetNormalizedChildNodes(element)) { foreach (XmlNode childNode in elementChildNodes) {
XmlElement childElement = childNode as XmlElement; XmlElement childElement = childNode as XmlElement;
if (childElement != null) { if (childElement != null) {
if (childElement.NamespaceURI == XamlConstants.XamlNamespace) if (childElement.NamespaceURI == XamlConstants.XamlNamespace)
continue; continue;
if (ObjectChildElementIsPropertyElement(childElement)) { if (ObjectChildElementIsPropertyElement(childElement)) {
ParseObjectChildElementAsPropertyElement(obj, childElement, defaultProperty, defaultPropertyValue); ParseObjectChildElementAsPropertyElement(obj, childElement, defaultProperty);
continue; continue;
} }
} }
@ -308,9 +327,9 @@ namespace ICSharpCode.WpfDesign.XamlDom
continue; continue;
XamlPropertyValue childValue = ParseValue(childNode); XamlPropertyValue childValue = ParseValue(childNode);
if (childValue != null) { if (childValue != null) {
if (defaultProperty != null && defaultProperty.IsCollection) { if (collectionProperty != null) {
defaultCollectionProperty.ParserAddCollectionElement(null, childValue); collectionProperty.ParserAddCollectionElement(collectionPropertyElement, childValue);
CollectionSupport.AddToCollection(defaultProperty.ReturnType, defaultPropertyValue, childValue); CollectionSupport.AddToCollection(collectionType, collectionInstance, childValue);
} else { } else {
if (defaultProperty == null) if (defaultProperty == null)
throw new XamlLoadException("This element does not have a default value, cannot assign to it"); throw new XamlLoadException("This element does not have a default value, cannot assign to it");
@ -386,6 +405,16 @@ namespace ICSharpCode.WpfDesign.XamlDom
return null; return null;
} }
static XamlProperty FindExistingXamlProperty(XamlObject obj, XamlPropertyInfo propertyInfo)
{
foreach (XamlProperty existing in obj.Properties) {
if (existing.propertyInfo.FullyQualifiedName == propertyInfo.FullyQualifiedName)
return existing;
}
throw new XamlLoadException("Existing XamlProperty " + propertyInfo.FullyQualifiedName + " not found.");
}
static XamlPropertyInfo GetDefaultProperty(Type elementType) static XamlPropertyInfo GetDefaultProperty(Type elementType)
{ {
foreach (ContentPropertyAttribute cpa in elementType.GetCustomAttributes(typeof(ContentPropertyAttribute), true)) { foreach (ContentPropertyAttribute cpa in elementType.GetCustomAttributes(typeof(ContentPropertyAttribute), true)) {
@ -531,7 +560,12 @@ namespace ICSharpCode.WpfDesign.XamlDom
return element.LocalName.Contains("."); return element.LocalName.Contains(".");
} }
void ParseObjectChildElementAsPropertyElement(XamlObject obj, XmlElement element, XamlPropertyInfo defaultProperty, object defaultPropertyValue) static bool IsElementChildACollectionForProperty(XamlTypeFinder typeFinder, XmlElement element, XamlPropertyInfo propertyInfo)
{
return element.ChildNodes.Count == 1 && propertyInfo.ReturnType.IsAssignableFrom(FindType(typeFinder, element.FirstChild.NamespaceURI, element.FirstChild.LocalName));
}
void ParseObjectChildElementAsPropertyElement(XamlObject obj, XmlElement element, XamlPropertyInfo defaultProperty)
{ {
Debug.Assert(element.LocalName.Contains(".")); Debug.Assert(element.LocalName.Contains("."));
// this is a element property syntax // this is a element property syntax
@ -540,23 +574,29 @@ namespace ICSharpCode.WpfDesign.XamlDom
bool valueWasSet = false; bool valueWasSet = false;
object collectionInstance = null; object collectionInstance = null;
bool isElementChildACollectionForProperty = false;
XamlProperty collectionProperty = null; XamlProperty collectionProperty = null;
if (propertyInfo.IsCollection) { if (propertyInfo.IsCollection) {
if (defaultProperty != null && defaultProperty.FullyQualifiedName == propertyInfo.FullyQualifiedName) { if (defaultProperty != null && defaultProperty.FullyQualifiedName == propertyInfo.FullyQualifiedName) {
collectionInstance = defaultPropertyValue;
foreach (XamlProperty existing in obj.Properties) { foreach (XamlProperty existing in obj.Properties) {
if (existing.propertyInfo == defaultProperty) { if (existing.propertyInfo == defaultProperty) {
collectionProperty = existing; collectionProperty = existing;
break; break;
} }
} }
} else {
collectionInstance = propertyInfo.GetValue(obj.Instance);
} }
if (collectionProperty == null) { if (collectionProperty == null) {
obj.AddProperty(collectionProperty = new XamlProperty(obj, propertyInfo)); obj.AddProperty(collectionProperty = new XamlProperty(obj, propertyInfo));
} }
collectionProperty.ParserSetPropertyElement(element);
isElementChildACollectionForProperty = IsElementChildACollectionForProperty(settings.TypeFinder, element, propertyInfo);
if (isElementChildACollectionForProperty)
collectionProperty.ParserSetPropertyElement((XmlElement)element.FirstChild);
else {
collectionInstance = collectionProperty.propertyInfo.GetValue(obj.Instance);
collectionProperty.ParserSetPropertyElement(element);
}
} }
XmlSpace oldXmlSpace = currentXmlSpace; XmlSpace oldXmlSpace = currentXmlSpace;
@ -568,7 +608,10 @@ namespace ICSharpCode.WpfDesign.XamlDom
XamlPropertyValue childValue = ParseValue(childNode); XamlPropertyValue childValue = ParseValue(childNode);
if (childValue != null) { if (childValue != null) {
if (propertyInfo.IsCollection) { if (propertyInfo.IsCollection) {
if (collectionInstance!=null) { if (isElementChildACollectionForProperty) {
collectionProperty.PropertyValue = childValue;
}
else {
CollectionSupport.AddToCollection(propertyInfo.ReturnType, collectionInstance, childValue); CollectionSupport.AddToCollection(propertyInfo.ReturnType, collectionInstance, childValue);
collectionProperty.ParserAddCollectionElement(element, childValue); collectionProperty.ParserAddCollectionElement(element, childValue);
} }

36
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs

@ -286,11 +286,43 @@ namespace ICSharpCode.WpfDesign.XamlDom
); );
} }
static XmlNode FindChildNode(XmlNode node, string localName, string namespaceURI)
{
foreach (XmlNode childNode in node.ChildNodes) {
if (childNode.LocalName == localName && childNode.NamespaceURI == namespaceURI)
return childNode;
}
return null;
}
bool IsNodeCollectionForThisProperty(XmlNode node)
{
return _propertyElement == null && this.PropertyName != this.ParentObject.ContentPropertyName && this.ReturnType.IsAssignableFrom(this.ParentObject.OwnerDocument.TypeFinder.GetType(node.NamespaceURI, node.LocalName));
}
internal void AddChildNodeToProperty(XmlNode newChildNode) internal void AddChildNodeToProperty(XmlNode newChildNode)
{ {
if (this.IsCollection) { if (this.IsCollection) {
// this is the default collection if (IsNodeCollectionForThisProperty(newChildNode)) {
InsertNodeInCollection(newChildNode, collectionElements.Count); XmlNode parentNode = FindChildNode(parentObject.XmlElement, parentObject.ElementType.Name + "." + this.PropertyName, parentObject.OwnerDocument.GetNamespaceFor(parentObject.ElementType));
if (parentNode == null) {
parentNode = CreatePropertyElement();
parentObject.XmlElement.AppendChild(parentNode);
}
else if (parentNode.ChildNodes.Count > 0)
throw new XamlLoadException("Collection property node must have no children when adding collection element.");
parentNode.AppendChild(newChildNode);
_propertyElement = (XmlElement)newChildNode;
}
else {
// this is the default collection
InsertNodeInCollection(newChildNode, collectionElements.Count);
}
return; return;
} }
if (_propertyElement == null) { if (_propertyElement == null) {

Loading…
Cancel
Save