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

Commit 9f719f9

Browse files
author
gumme
committed
Merge branch 'WpfDesignerParserFixes'
Conflicts: src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs
2 parents 3e27053 + b401bc5 commit 9f719f9

4 files changed

Lines changed: 128 additions & 18 deletions

File tree

src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/ExampleClassContainer.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77

88
namespace ICSharpCode.WpfDesign.Tests.XamlDom
99
{
10+
public class ExampleClassList : List<ExampleClass>
11+
{
12+
}
13+
1014
[ContentProperty("List")]
1115
public class ExampleClassContainer : ExampleClass
1216
{
@@ -18,5 +22,18 @@ public List<ExampleClass> List {
1822
return list;
1923
}
2024
}
25+
26+
ExampleClassList otherList = new ExampleClassList();
27+
28+
public ExampleClassList OtherList {
29+
get {
30+
TestHelperLog.Log("OtherList.get " + Identity);
31+
return otherList;
32+
}
33+
set {
34+
TestHelperLog.Log("OtherList.set " + Identity);
35+
otherList = value;
36+
}
37+
}
2138
}
2239
}

src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/SimpleLoadTests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,24 @@ public void ContainerImplicitList()
190190
");
191191
}
192192

193+
[Test]
194+
public void ContainerExplicitList()
195+
{
196+
TestLoading(@"
197+
<ExampleClassContainer
198+
xmlns=""" + XamlTypeFinderTests.XamlDomTestsNamespace + @"""
199+
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
200+
<ExampleClassContainer.OtherList>
201+
<ExampleClassList>
202+
<ExampleClass OtherProp=""a""> </ExampleClass>
203+
<ExampleClass OtherProp=""b"" />
204+
<ExampleClass OtherProp=""c"" />
205+
</ExampleClassList>
206+
</ExampleClassContainer.OtherList>
207+
</ExampleClassContainer>
208+
");
209+
}
210+
193211
[Test]
194212
public void ExampleServiceTest()
195213
{

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)