Browse Source

Merge pull request #470 from gumme/WpfDesignerCollectionUndoFix

Wpf designer fixes for explicit collection and dictionary
pull/474/head
Daniel Grunwald 11 years ago
parent
commit
e4a573debd
  1. 253
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs
  2. 3
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs
  3. 15
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs
  4. 10
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs

253
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs

@ -149,6 +149,176 @@ namespace ICSharpCode.WpfDesign.Tests.Designer @@ -149,6 +149,176 @@ 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("<Button/>");
UndoService s = button.Context.Services.GetService<UndoService>();
IComponentService component = button.Context.Services.Component;
string expectedXamlWithList;
DesignItemProperty otherListProp;
Assert.IsFalse(s.CanUndo);
Assert.IsFalse(s.CanRedo);
using (ChangeGroup g = button.OpenGroup("UndoRedoListInternal test")) {
DesignItem containerItem = component.RegisterComponentForDesigner(new ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassContainer());
otherListProp = containerItem.Properties["OtherList"];
if(useExplicitList) {
otherListProp.SetValue(new ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassList());
expectedXamlWithList = @"<Button>
<Button.Tag>
<Controls0:ExampleClassContainer>
<Controls0:ExampleClassContainer.OtherList>
<Controls0:ExampleClassList>
<Controls0:ExampleClass StringProp=""String value"" />
</Controls0:ExampleClassList>
</Controls0:ExampleClassContainer.OtherList>
</Controls0:ExampleClassContainer>
</Button.Tag>
</Button>";
} else {
expectedXamlWithList = @"<Button>
<Button.Tag>
<Controls0:ExampleClassContainer>
<Controls0:ExampleClassContainer.OtherList>
<Controls0:ExampleClass StringProp=""String value"" />
</Controls0:ExampleClassContainer.OtherList>
</Controls0:ExampleClassContainer>
</Button.Tag>
</Button>";
}
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 + "\"");
otherListProp = button.Properties["Tag"].Value.Properties["OtherList"];
Assert.IsTrue(((ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassList)otherListProp.ValueOnInstance).Count == otherListProp.CollectionElements.Count);
s.Undo();
Assert.IsFalse(s.CanUndo);
Assert.IsTrue(s.CanRedo);
AssertCanvasDesignerOutput("<Button>\n</Button>", 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 + "\"");
otherListProp = button.Properties["Tag"].Value.Properties["OtherList"];
Assert.IsTrue(((ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassList)otherListProp.ValueOnInstance).Count == otherListProp.CollectionElements.Count);
AssertLog("");
}
[Test]
public void UndoRedoImplicitDictionary()
{
UndoRedoDictionaryInternal(false);
}
[Test]
public void UndoRedoExplicitDictionary()
{
UndoRedoDictionaryInternal(true);
}
void UndoRedoDictionaryInternal(bool useExplicitDictionary)
{
DesignItem button = CreateCanvasContext("<Button/>");
UndoService s = button.Context.Services.GetService<UndoService>();
IComponentService component = button.Context.Services.Component;
string expectedXamlWithDictionary;
DesignItemProperty dictionaryProp;
Assert.IsFalse(s.CanUndo);
Assert.IsFalse(s.CanRedo);
using (ChangeGroup g = button.OpenGroup("UndoRedoDictionaryInternal test")) {
DesignItem containerItem = component.RegisterComponentForDesigner(new ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassContainer());
dictionaryProp = containerItem.Properties["Dictionary"];
if(useExplicitDictionary) {
dictionaryProp.SetValue(new ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassDictionary());
expectedXamlWithDictionary = @"<Button>
<Button.Tag>
<Controls0:ExampleClassContainer>
<Controls0:ExampleClassContainer.Dictionary>
<Controls0:ExampleClassDictionary>
<Controls0:ExampleClass x:Key=""testKey"" StringProp=""String value"" />
</Controls0:ExampleClassDictionary>
</Controls0:ExampleClassContainer.Dictionary>
</Controls0:ExampleClassContainer>
</Button.Tag>
</Button>";
} else {
expectedXamlWithDictionary = @"<Button>
<Button.Tag>
<Controls0:ExampleClassContainer>
<Controls0:ExampleClassContainer.Dictionary>
<Controls0:ExampleClass x:Key=""testKey"" StringProp=""String value"" />
</Controls0:ExampleClassContainer.Dictionary>
</Controls0:ExampleClassContainer>
</Button.Tag>
</Button>";
}
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>\n</Button>", 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()
@ -254,6 +424,89 @@ namespace ICSharpCode.WpfDesign.Tests.Designer @@ -254,6 +424,89 @@ namespace ICSharpCode.WpfDesign.Tests.Designer
AssertLog("");
}
[Test]
public void ClearExplicitList()
{
DesignItem button = CreateCanvasContext("<Button/>");
button.Properties["Tag"].SetValue(new ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassContainer());
var containerItem = button.Properties["Tag"].Value;
var otherListProp = containerItem.Properties["OtherList"];
otherListProp.SetValue(new ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassList());
DesignItem exampleClassItem = button.Context.Services.Component.RegisterComponentForDesigner(new ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClass());
exampleClassItem.Properties["StringProp"].SetValue("String value");
otherListProp.CollectionElements.Add(exampleClassItem);
var listInstance = (ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassList)otherListProp.ValueOnInstance;
Assert.AreEqual(1, listInstance.Count);
Assert.AreEqual(1, otherListProp.CollectionElements.Count);
button.Properties["Tag"].Value.Properties["OtherList"].CollectionElements.Clear();
Assert.AreEqual(0, listInstance.Count);
Assert.AreEqual(0, otherListProp.CollectionElements.Count);
AssertCanvasDesignerOutput(@"<Button>
<Button.Tag>
<Controls0:ExampleClassContainer>
<Controls0:ExampleClassContainer.OtherList>
<Controls0:ExampleClassList>
</Controls0:ExampleClassList>
</Controls0:ExampleClassContainer.OtherList>
</Controls0:ExampleClassContainer>
</Button.Tag>
</Button>", button.Context, "xmlns:Controls0=\"" + ICSharpCode.WpfDesign.Tests.XamlDom.XamlTypeFinderTests.XamlDomTestsNamespace + "\"");
AssertLog("");
}
[Test]
public void ClearExplicitDictionary()
{
DesignItem button = CreateCanvasContext("<Button/>");
button.Properties["Tag"].SetValue(new ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassContainer());
var containerItem = button.Properties["Tag"].Value;
var dictionaryProp = containerItem.Properties["Dictionary"];
dictionaryProp.SetValue(new ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassDictionary());
DesignItem exampleClassItem = button.Context.Services.Component.RegisterComponentForDesigner(new ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClass());
exampleClassItem.Key = "testKey";
exampleClassItem.Properties["StringProp"].SetValue("String value");
dictionaryProp.CollectionElements.Add(exampleClassItem);
var dictionaryInstance = (ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassDictionary)dictionaryProp.ValueOnInstance;
Assert.AreEqual(1, dictionaryInstance.Count);
Assert.AreEqual(1, dictionaryProp.CollectionElements.Count);
button.Properties["Tag"].Value.Properties["Dictionary"].CollectionElements.Clear();
Assert.AreEqual(0, dictionaryInstance.Count);
Assert.AreEqual(0, dictionaryProp.CollectionElements.Count);
dictionaryProp.CollectionElements.Add(exampleClassItem);
Assert.AreEqual(1, dictionaryInstance.Count);
Assert.AreEqual(1, dictionaryProp.CollectionElements.Count);
button.Properties["Tag"].Value.Properties["Dictionary"].CollectionElements.Clear();
Assert.AreEqual(0, dictionaryInstance.Count);
Assert.AreEqual(0, dictionaryProp.CollectionElements.Count);
AssertCanvasDesignerOutput(@"<Button>
<Button.Tag>
<Controls0:ExampleClassContainer>
<Controls0:ExampleClassContainer.Dictionary>
<Controls0:ExampleClassDictionary>
</Controls0:ExampleClassDictionary>
</Controls0:ExampleClassContainer.Dictionary>
</Controls0:ExampleClassContainer>
</Button.Tag>
</Button>", button.Context, "xmlns:Controls0=\"" + ICSharpCode.WpfDesign.Tests.XamlDom.XamlTypeFinderTests.XamlDomTestsNamespace + "\"");
AssertLog("");
}
[Test]
public void AddMultiBindingToTextBox()
{

3
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs

@ -54,7 +54,8 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -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();

15
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs

@ -154,5 +154,20 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -154,5 +154,20 @@ namespace ICSharpCode.WpfDesign.XamlDom
new object[] { item },
CultureInfo.InvariantCulture);
}
/// <summary>
/// Removes an item instance from the specified collection.
/// </summary>
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);
}
}
}
}

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

@ -254,13 +254,21 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -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;
}
}

Loading…
Cancel
Save