Skip to content
This repository was archived by the owner on Oct 16, 2020. It is now read-only.

Commit b401bc5

Browse files
author
gumme
committed
Fixed parser so it can handle explicit lists.
1 parent 4d28820 commit b401bc5

2 files changed

Lines changed: 93 additions & 18 deletions

File tree

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

Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -285,32 +285,51 @@ XamlObject ParseObject(XmlElement element)
285285
void ParseObjectContent(XamlObject obj, XmlElement element, XamlPropertyInfo defaultProperty, XamlTextValue initializeFromTextValueInsteadOfConstructor)
286286
{
287287
bool isDefaultValueSet = false;
288-
object defaultPropertyValue = null;
289-
XamlProperty defaultCollectionProperty = null;
290288

291-
if (defaultProperty != null && defaultProperty.IsCollection && !element.IsEmpty) {
292-
defaultPropertyValue = defaultProperty.GetValue(obj.Instance);
293-
obj.AddProperty(defaultCollectionProperty = new XamlProperty(obj, defaultProperty));
289+
XamlProperty collectionProperty = null;
290+
object collectionInstance = null;
291+
Type collectionType = null;
292+
XmlElement collectionPropertyElement = null;
293+
var elementChildNodes = GetNormalizedChildNodes(element);
294+
295+
if (defaultProperty == null && obj.Instance != null && CollectionSupport.IsCollectionType(obj.Instance.GetType())) {
296+
XamlObject parentObj = obj.ParentObject;
297+
var parentElement = element.ParentNode;
298+
XamlPropertyInfo propertyInfo = GetPropertyInfo(settings.TypeFinder, parentObj.Instance, parentObj.ElementType, parentElement.NamespaceURI, parentElement.LocalName);
299+
collectionProperty = FindExistingXamlProperty(parentObj, propertyInfo);
300+
collectionInstance = obj.Instance;
301+
collectionType = obj.ElementType;
302+
collectionPropertyElement = element;
303+
} else if (defaultProperty != null && defaultProperty.IsCollection && !element.IsEmpty) {
304+
foreach (XmlNode childNode in elementChildNodes) {
305+
XmlElement childElement = childNode as XmlElement;
306+
if (childElement == null || !ObjectChildElementIsPropertyElement(childElement)) {
307+
obj.AddProperty(collectionProperty = new XamlProperty(obj, defaultProperty));
308+
collectionType = defaultProperty.ReturnType;
309+
collectionInstance = defaultProperty.GetValue(obj.Instance);
310+
break;
311+
}
312+
}
294313
}
295314

296-
foreach (XmlNode childNode in GetNormalizedChildNodes(element)) {
315+
foreach (XmlNode childNode in elementChildNodes) {
297316
XmlElement childElement = childNode as XmlElement;
298317
if (childElement != null) {
299318
if (childElement.NamespaceURI == XamlConstants.XamlNamespace)
300319
continue;
301320

302321
if (ObjectChildElementIsPropertyElement(childElement)) {
303-
ParseObjectChildElementAsPropertyElement(obj, childElement, defaultProperty, defaultPropertyValue);
322+
ParseObjectChildElementAsPropertyElement(obj, childElement, defaultProperty);
304323
continue;
305324
}
306325
}
307326
if (initializeFromTextValueInsteadOfConstructor != null)
308327
continue;
309328
XamlPropertyValue childValue = ParseValue(childNode);
310329
if (childValue != null) {
311-
if (defaultProperty != null && defaultProperty.IsCollection) {
312-
defaultCollectionProperty.ParserAddCollectionElement(null, childValue);
313-
CollectionSupport.AddToCollection(defaultProperty.ReturnType, defaultPropertyValue, childValue);
330+
if (collectionProperty != null) {
331+
collectionProperty.ParserAddCollectionElement(collectionPropertyElement, childValue);
332+
CollectionSupport.AddToCollection(collectionType, collectionInstance, childValue);
314333
} else {
315334
if (defaultProperty == null)
316335
throw new XamlLoadException("This element does not have a default value, cannot assign to it");
@@ -386,6 +405,16 @@ XamlPropertyValue ParseValueCore(XmlNode childNode)
386405
return null;
387406
}
388407

408+
static XamlProperty FindExistingXamlProperty(XamlObject obj, XamlPropertyInfo propertyInfo)
409+
{
410+
foreach (XamlProperty existing in obj.Properties) {
411+
if (existing.propertyInfo.FullyQualifiedName == propertyInfo.FullyQualifiedName)
412+
return existing;
413+
}
414+
415+
throw new XamlLoadException("Existing XamlProperty " + propertyInfo.FullyQualifiedName + " not found.");
416+
}
417+
389418
static XamlPropertyInfo GetDefaultProperty(Type elementType)
390419
{
391420
foreach (ContentPropertyAttribute cpa in elementType.GetCustomAttributes(typeof(ContentPropertyAttribute), true)) {
@@ -531,7 +560,12 @@ static bool ObjectChildElementIsPropertyElement(XmlElement element)
531560
return element.LocalName.Contains(".");
532561
}
533562

534-
void ParseObjectChildElementAsPropertyElement(XamlObject obj, XmlElement element, XamlPropertyInfo defaultProperty, object defaultPropertyValue)
563+
static bool IsElementChildACollectionForProperty(XamlTypeFinder typeFinder, XmlElement element, XamlPropertyInfo propertyInfo)
564+
{
565+
return element.ChildNodes.Count == 1 && propertyInfo.ReturnType.IsAssignableFrom(FindType(typeFinder, element.FirstChild.NamespaceURI, element.FirstChild.LocalName));
566+
}
567+
568+
void ParseObjectChildElementAsPropertyElement(XamlObject obj, XmlElement element, XamlPropertyInfo defaultProperty)
535569
{
536570
Debug.Assert(element.LocalName.Contains("."));
537571
// this is a element property syntax
@@ -540,23 +574,29 @@ void ParseObjectChildElementAsPropertyElement(XamlObject obj, XmlElement element
540574
bool valueWasSet = false;
541575

542576
object collectionInstance = null;
577+
bool isElementChildACollectionForProperty = false;
543578
XamlProperty collectionProperty = null;
544579
if (propertyInfo.IsCollection) {
545580
if (defaultProperty != null && defaultProperty.FullyQualifiedName == propertyInfo.FullyQualifiedName) {
546-
collectionInstance = defaultPropertyValue;
547581
foreach (XamlProperty existing in obj.Properties) {
548582
if (existing.propertyInfo == defaultProperty) {
549583
collectionProperty = existing;
550584
break;
551585
}
552586
}
553-
} else {
554-
collectionInstance = propertyInfo.GetValue(obj.Instance);
555587
}
588+
556589
if (collectionProperty == null) {
557590
obj.AddProperty(collectionProperty = new XamlProperty(obj, propertyInfo));
558591
}
559-
collectionProperty.ParserSetPropertyElement(element);
592+
593+
isElementChildACollectionForProperty = IsElementChildACollectionForProperty(settings.TypeFinder, element, propertyInfo);
594+
if (isElementChildACollectionForProperty)
595+
collectionProperty.ParserSetPropertyElement((XmlElement)element.FirstChild);
596+
else {
597+
collectionInstance = collectionProperty.propertyInfo.GetValue(obj.Instance);
598+
collectionProperty.ParserSetPropertyElement(element);
599+
}
560600
}
561601

562602
XmlSpace oldXmlSpace = currentXmlSpace;
@@ -568,7 +608,10 @@ void ParseObjectChildElementAsPropertyElement(XamlObject obj, XmlElement element
568608
XamlPropertyValue childValue = ParseValue(childNode);
569609
if (childValue != null) {
570610
if (propertyInfo.IsCollection) {
571-
if (collectionInstance!=null) {
611+
if (isElementChildACollectionForProperty) {
612+
collectionProperty.PropertyValue = childValue;
613+
}
614+
else {
572615
CollectionSupport.AddToCollection(propertyInfo.ReturnType, collectionInstance, childValue);
573616
collectionProperty.ParserAddCollectionElement(element, childValue);
574617
}

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

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,11 +286,43 @@ XmlElement CreatePropertyElement()
286286
);
287287
}
288288

289+
static XmlNode FindChildNode(XmlNode node, string localName, string namespaceURI)
290+
{
291+
foreach (XmlNode childNode in node.ChildNodes) {
292+
if (childNode.LocalName == localName && childNode.NamespaceURI == namespaceURI)
293+
return childNode;
294+
}
295+
296+
return null;
297+
}
298+
299+
bool IsNodeCollectionForThisProperty(XmlNode node)
300+
{
301+
return _propertyElement == null && this.PropertyName != this.ParentObject.ContentPropertyName && this.ReturnType.IsAssignableFrom(this.ParentObject.OwnerDocument.TypeFinder.GetType(node.NamespaceURI, node.LocalName));
302+
}
303+
289304
internal void AddChildNodeToProperty(XmlNode newChildNode)
290305
{
291306
if (this.IsCollection) {
292-
// this is the default collection
293-
InsertNodeInCollection(newChildNode, collectionElements.Count);
307+
if (IsNodeCollectionForThisProperty(newChildNode)) {
308+
XmlNode parentNode = FindChildNode(parentObject.XmlElement, parentObject.ElementType.Name + "." + this.PropertyName, parentObject.OwnerDocument.GetNamespaceFor(parentObject.ElementType));
309+
310+
if (parentNode == null) {
311+
parentNode = CreatePropertyElement();
312+
313+
parentObject.XmlElement.AppendChild(parentNode);
314+
}
315+
else if (parentNode.ChildNodes.Count > 0)
316+
throw new XamlLoadException("Collection property node must have no children when adding collection element.");
317+
318+
parentNode.AppendChild(newChildNode);
319+
_propertyElement = (XmlElement)newChildNode;
320+
}
321+
else {
322+
// this is the default collection
323+
InsertNodeInCollection(newChildNode, collectionElements.Count);
324+
}
325+
294326
return;
295327
}
296328
if (_propertyElement == null) {

0 commit comments

Comments
 (0)