From 300417bb5f68582f2b628df7e93f14c4bd820c22 Mon Sep 17 00:00:00 2001 From: gumme Date: Wed, 7 May 2014 14:34:01 +0200 Subject: [PATCH 1/2] Added tests for undo/redo operations on implicit and explicit lists. Fixed bug where explicit collection was not handled correctly when resetting a XamlProperty. --- .../Tests/Designer/ModelTests.cs | 78 +++++++++++++++++++ .../WpfDesign.XamlDom/Project/XamlProperty.cs | 10 ++- 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs index dc675552f7..bc0d55de97 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs @@ -149,6 +149,84 @@ namespace ICSharpCode.WpfDesign.Tests.Designer AssertLog(""); } + [Test] + public void UndoRedoImplicitList() + { + UndoRedoListInternal(false); + } + + [Test] + public void UndoRedoExplicitList() + { + UndoRedoListInternal(true); + } + + void UndoRedoListInternal(bool useExplicitList) + { + DesignItem button = CreateCanvasContext(""; + } + else { + expectedXamlWithList = @""; + } + + DesignItem exampleClassItem = component.RegisterComponentForDesigner(new ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClass()); + exampleClassItem.Properties["StringProp"].SetValue("String value"); + otherListProp.CollectionElements.Add(exampleClassItem); + + button.Properties["Tag"].SetValue(containerItem); + g.Commit(); + } + + Assert.IsTrue(s.CanUndo); + Assert.IsFalse(s.CanRedo); + AssertCanvasDesignerOutput(expectedXamlWithList, button.Context, "xmlns:Controls0=\"" + ICSharpCode.WpfDesign.Tests.XamlDom.XamlTypeFinderTests.XamlDomTestsNamespace + "\""); + + s.Undo(); + Assert.IsFalse(s.CanUndo); + Assert.IsTrue(s.CanRedo); + AssertCanvasDesignerOutput("", button.Context, "xmlns:Controls0=\"" + ICSharpCode.WpfDesign.Tests.XamlDom.XamlTypeFinderTests.XamlDomTestsNamespace + "\""); + + s.Redo(); + Assert.IsTrue(s.CanUndo); + Assert.IsFalse(s.CanRedo); + AssertCanvasDesignerOutput(expectedXamlWithList, button.Context, "xmlns:Controls0=\"" + ICSharpCode.WpfDesign.Tests.XamlDom.XamlTypeFinderTests.XamlDomTestsNamespace + "\""); + + AssertLog(""); + } [Test] public void AddTextBoxToCanvas() diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs index 9fbeab0717..eee4a6848e 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs @@ -254,13 +254,21 @@ namespace ICSharpCode.WpfDesign.XamlDom void ResetInternal() { + bool isExplicitCollection = false; + if (propertyValue != null) { + isExplicitCollection = IsCollection; + propertyValue.RemoveNodeFromParent(); propertyValue.ParentProperty = null; propertyValue = null; } if (_propertyElement != null) { - _propertyElement.ParentNode.RemoveChild(_propertyElement); + Debug.Assert(!isExplicitCollection || _propertyElement.ParentNode == null); + + if (!isExplicitCollection) { + _propertyElement.ParentNode.RemoveChild(_propertyElement); + } _propertyElement = null; } } From 5ccc93f254dfe3ddc120beaca105c0fca50742f1 Mon Sep 17 00:00:00 2001 From: gumme Date: Fri, 9 May 2014 07:34:14 +0200 Subject: [PATCH 2/2] Added tests for undo/redo operations on implicit and explicit dictionaries. Added tests for clearing explicit lists and dictionaries. Fixed so an IDictionary item is removed using the item key. --- .../Tests/Designer/ModelTests.cs | 183 +++++++++++++++++- .../Project/CollectionElementsCollection.cs | 3 +- .../Project/CollectionSupport.cs | 15 ++ 3 files changed, 196 insertions(+), 5 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs index bc0d55de97..44d4611df9 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs @@ -167,6 +167,7 @@ namespace ICSharpCode.WpfDesign.Tests.Designer UndoService s = button.Context.Services.GetService(); IComponentService component = button.Context.Services.Component; string expectedXamlWithList; + DesignItemProperty otherListProp; Assert.IsFalse(s.CanUndo); Assert.IsFalse(s.CanRedo); @@ -174,7 +175,7 @@ namespace ICSharpCode.WpfDesign.Tests.Designer using (ChangeGroup g = button.OpenGroup("UndoRedoListInternal test")) { DesignItem containerItem = component.RegisterComponentForDesigner(new ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassContainer()); - var otherListProp = containerItem.Properties["OtherList"]; + otherListProp = containerItem.Properties["OtherList"]; if(useExplicitList) { otherListProp.SetValue(new ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassList()); @@ -190,8 +191,7 @@ namespace ICSharpCode.WpfDesign.Tests.Designer "; - } - else { + } else { expectedXamlWithList = @""; + } else { + expectedXamlWithDictionary = @""; + } + + DesignItem exampleClassItem = component.RegisterComponentForDesigner(new ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClass()); + exampleClassItem.Key = "testKey"; + exampleClassItem.Properties["StringProp"].SetValue("String value"); + dictionaryProp.CollectionElements.Add(exampleClassItem); + + button.Properties["Tag"].SetValue(containerItem); + g.Commit(); + } + + Assert.IsTrue(s.CanUndo); + Assert.IsFalse(s.CanRedo); + AssertCanvasDesignerOutput(expectedXamlWithDictionary, button.Context, "xmlns:Controls0=\"" + ICSharpCode.WpfDesign.Tests.XamlDom.XamlTypeFinderTests.XamlDomTestsNamespace + "\""); + + dictionaryProp = button.Properties["Tag"].Value.Properties["Dictionary"]; + Assert.IsTrue(((ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassDictionary)dictionaryProp.ValueOnInstance).Count == dictionaryProp.CollectionElements.Count); + + s.Undo(); + Assert.IsFalse(s.CanUndo); + Assert.IsTrue(s.CanRedo); + AssertCanvasDesignerOutput("", button.Context, "xmlns:Controls0=\"" + ICSharpCode.WpfDesign.Tests.XamlDom.XamlTypeFinderTests.XamlDomTestsNamespace + "\""); + + s.Redo(); + Assert.IsTrue(s.CanUndo); + Assert.IsFalse(s.CanRedo); + AssertCanvasDesignerOutput(expectedXamlWithDictionary, button.Context, "xmlns:Controls0=\"" + ICSharpCode.WpfDesign.Tests.XamlDom.XamlTypeFinderTests.XamlDomTestsNamespace + "\""); + + dictionaryProp = button.Properties["Tag"].Value.Properties["Dictionary"]; + Assert.IsTrue(((ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassDictionary)dictionaryProp.ValueOnInstance).Count == dictionaryProp.CollectionElements.Count); + AssertLog(""); - } + } [Test] public void AddTextBoxToCanvas() @@ -332,6 +424,89 @@ namespace ICSharpCode.WpfDesign.Tests.Designer AssertLog(""); } + [Test] + public void ClearExplicitList() + { + DesignItem button = CreateCanvasContext("", button.Context, "xmlns:Controls0=\"" + ICSharpCode.WpfDesign.Tests.XamlDom.XamlTypeFinderTests.XamlDomTestsNamespace + "\""); + AssertLog(""); + } + + [Test] + public void ClearExplicitDictionary() + { + DesignItem button = CreateCanvasContext("", button.Context, "xmlns:Controls0=\"" + ICSharpCode.WpfDesign.Tests.XamlDom.XamlTypeFinderTests.XamlDomTestsNamespace + "\""); + AssertLog(""); + } + [Test] public void AddMultiBindingToTextBox() { diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs index 86bc31adef..6566897e28 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs @@ -54,7 +54,8 @@ namespace ICSharpCode.WpfDesign.XamlDom XamlPropertyInfo info = property.propertyInfo; object collection = info.GetValue(property.ParentObject.Instance); if (!CollectionSupport.RemoveItemAt(info.ReturnType, collection, index)) { - CollectionSupport.RemoveItem(info.ReturnType, collection, this[index].GetValueFor(info)); + var propertyValue = this[index]; + CollectionSupport.RemoveItem(info.ReturnType, collection, propertyValue.GetValueFor(info), propertyValue); } this[index].RemoveNodeFromParent(); diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs index cf36fed5a4..09a3b28beb 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs @@ -154,5 +154,20 @@ namespace ICSharpCode.WpfDesign.XamlDom new object[] { item }, CultureInfo.InvariantCulture); } + + /// + /// Removes an item instance from the specified collection. + /// + internal static void RemoveItem(Type collectionType, object collectionInstance, object item, XamlPropertyValue element) + { + var dictionary = collectionInstance as IDictionary; + var xamlObject = element as XamlObject; + + if (dictionary != null && xamlObject != null) { + dictionary.Remove(xamlObject.GetXamlAttribute("Key")); + } else { + RemoveItem(collectionType, collectionInstance, item); + } + } } }