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 @@ -285,22 +285,41 @@ namespace ICSharpCode.WpfDesign.XamlDom
void ParseObjectContent(XamlObject obj, XmlElement element, XamlPropertyInfo defaultProperty, XamlTextValue initializeFromTextValueInsteadOfConstructor)
{
bool isDefaultValueSet = false;
object defaultPropertyValue = null;
XamlProperty defaultCollectionProperty = null;
if (defaultProperty != null && defaultProperty.IsCollection && !element.IsEmpty) {
defaultPropertyValue = defaultProperty.GetValue(obj.Instance);
obj.AddProperty(defaultCollectionProperty = new XamlProperty(obj, defaultProperty));
XamlProperty collectionProperty = null;
object collectionInstance = null;
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;
if (childElement != null) {
if (childElement.NamespaceURI == XamlConstants.XamlNamespace)
continue;
if (ObjectChildElementIsPropertyElement(childElement)) {
ParseObjectChildElementAsPropertyElement(obj, childElement, defaultProperty, defaultPropertyValue);
ParseObjectChildElementAsPropertyElement(obj, childElement, defaultProperty);
continue;
}
}
@ -308,9 +327,9 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -308,9 +327,9 @@ namespace ICSharpCode.WpfDesign.XamlDom
continue;
XamlPropertyValue childValue = ParseValue(childNode);
if (childValue != null) {
if (defaultProperty != null && defaultProperty.IsCollection) {
defaultCollectionProperty.ParserAddCollectionElement(null, childValue);
CollectionSupport.AddToCollection(defaultProperty.ReturnType, defaultPropertyValue, childValue);
if (collectionProperty != null) {
collectionProperty.ParserAddCollectionElement(collectionPropertyElement, childValue);
CollectionSupport.AddToCollection(collectionType, collectionInstance, childValue);
} else {
if (defaultProperty == null)
throw new XamlLoadException("This element does not have a default value, cannot assign to it");
@ -386,6 +405,16 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -386,6 +405,16 @@ namespace ICSharpCode.WpfDesign.XamlDom
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)
{
foreach (ContentPropertyAttribute cpa in elementType.GetCustomAttributes(typeof(ContentPropertyAttribute), true)) {
@ -531,7 +560,12 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -531,7 +560,12 @@ namespace ICSharpCode.WpfDesign.XamlDom
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("."));
// this is a element property syntax
@ -540,23 +574,29 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -540,23 +574,29 @@ namespace ICSharpCode.WpfDesign.XamlDom
bool valueWasSet = false;
object collectionInstance = null;
bool isElementChildACollectionForProperty = false;
XamlProperty collectionProperty = null;
if (propertyInfo.IsCollection) {
if (defaultProperty != null && defaultProperty.FullyQualifiedName == propertyInfo.FullyQualifiedName) {
collectionInstance = defaultPropertyValue;
foreach (XamlProperty existing in obj.Properties) {
if (existing.propertyInfo == defaultProperty) {
collectionProperty = existing;
break;
}
}
} else {
collectionInstance = propertyInfo.GetValue(obj.Instance);
}
if (collectionProperty == null) {
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;
@ -568,7 +608,10 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -568,7 +608,10 @@ namespace ICSharpCode.WpfDesign.XamlDom
XamlPropertyValue childValue = ParseValue(childNode);
if (childValue != null) {
if (propertyInfo.IsCollection) {
if (collectionInstance!=null) {
if (isElementChildACollectionForProperty) {
collectionProperty.PropertyValue = childValue;
}
else {
CollectionSupport.AddToCollection(propertyInfo.ReturnType, collectionInstance, childValue);
collectionProperty.ParserAddCollectionElement(element, childValue);
}

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

@ -286,11 +286,43 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -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)
{
if (this.IsCollection) {
// this is the default collection
InsertNodeInCollection(newChildNode, collectionElements.Count);
if (IsNodeCollectionForThisProperty(newChildNode)) {
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;
}
if (_propertyElement == null) {

Loading…
Cancel
Save