Browse Source

Using IList for Insert/Add of items if implemented. This fixes so collections inside System.Windows.Input namespace is synchronized with SD internal collection when undo/redo operations have executed on the collection.

pull/657/head
gumme 11 years ago
parent
commit
91a773da7b
  1. 57
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs
  2. 50
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/CollectionTests.cs
  3. 26
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs

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

@ -320,6 +320,63 @@ namespace ICSharpCode.WpfDesign.Tests.Designer @@ -320,6 +320,63 @@ namespace ICSharpCode.WpfDesign.Tests.Designer
AssertLog("");
}
[Test]
public void UndoRedoInputBindings()
{
DesignItem textBlock = CreateCanvasContext("<TextBlock/>");
UndoService s = textBlock.Context.Services.GetService<UndoService>();
IComponentService component = textBlock.Context.Services.Component;
Assert.IsFalse(s.CanUndo);
Assert.IsFalse(s.CanRedo);
DesignItemProperty inputbinding = textBlock.Properties["InputBindings"];
Assert.IsTrue(inputbinding.IsCollection);
const string expectedXaml = @"<TextBlock>
<TextBlock.InputBindings>
<MouseBinding Gesture=""LeftDoubleClick"" Command=""ApplicationCommands.New"" />
</TextBlock.InputBindings>
</TextBlock>";
using (ChangeGroup changeGroup = textBlock.Context.OpenGroup("", new[] { textBlock }))
{
DesignItem di = component.RegisterComponentForDesigner(new System.Windows.Input.MouseBinding());
di.Properties["Gesture"].SetValue(System.Windows.Input.MouseAction.LeftDoubleClick);
di.Properties["Command"].SetValue("ApplicationCommands.New");
inputbinding.CollectionElements.Add(di);
changeGroup.Commit();
}
Assert.IsTrue(s.CanUndo);
Assert.IsFalse(s.CanRedo);
AssertCanvasDesignerOutput(expectedXaml, textBlock.Context);
inputbinding = textBlock.Properties["InputBindings"];
Assert.IsTrue(((System.Windows.Input.InputBindingCollection)inputbinding.ValueOnInstance).Count == inputbinding.CollectionElements.Count);
const string undoXaml = @"<TextBlock>
<TextBlock.InputBindings>
</TextBlock.InputBindings>
</TextBlock>";
s.Undo();
Assert.IsFalse(s.CanUndo);
Assert.IsTrue(s.CanRedo);
AssertCanvasDesignerOutput(undoXaml, textBlock.Context);
s.Redo();
Assert.IsTrue(s.CanUndo);
Assert.IsFalse(s.CanRedo);
AssertCanvasDesignerOutput(expectedXaml, textBlock.Context);
Assert.IsTrue(((System.Windows.Input.InputBindingCollection)inputbinding.ValueOnInstance).Count == inputbinding.CollectionElements.Count);
AssertLog("");
}
[Test]
public void AddTextBoxToCanvas()
{

50
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/CollectionTests.cs

@ -20,5 +20,55 @@ namespace ICSharpCode.WpfDesign.Tests.XamlDom @@ -20,5 +20,55 @@ namespace ICSharpCode.WpfDesign.Tests.XamlDom
Assert.IsFalse(isCollection);
}
/// <summary>
/// This test is here do demonstrate a peculiarity (or bug) with collections inside System.Windows.Input namespace.
/// The problem is that inserting the first item into the collection will silently fail (Count still 0 after Insert), first item must use Add method.
/// </summary>
[Test]
public void InputCollectionsPeculiarityOrBug()
{
// InputBindingCollection START
var inputBindingCollection = new System.Windows.Input.InputBindingCollection();
// NOTE: this silently fails (Count is 0 after insert)
inputBindingCollection.Insert(0, new System.Windows.Input.MouseBinding());
Assert.IsTrue(inputBindingCollection.Count == 0);
inputBindingCollection.Add(new System.Windows.Input.MouseBinding());
Assert.IsTrue(inputBindingCollection.Count == 1);
inputBindingCollection.Insert(0, new System.Windows.Input.MouseBinding());
Assert.IsTrue(inputBindingCollection.Count == 2);
// InputBindingCollection END
// CommandBindingCollection START
var commandBindingCollection = new System.Windows.Input.CommandBindingCollection();
// NOTE: this silently fails (Count is 0 after insert)
commandBindingCollection.Insert(0, new System.Windows.Input.CommandBinding());
Assert.IsTrue(commandBindingCollection.Count == 0);
commandBindingCollection.Add(new System.Windows.Input.CommandBinding());
Assert.IsTrue(commandBindingCollection.Count == 1);
commandBindingCollection.Insert(0, new System.Windows.Input.CommandBinding());
Assert.IsTrue(commandBindingCollection.Count == 2);
// CommandBindingCollection END
// List START (how it probably should work...)
var list = new List<string>();
// NOTE: this is successful for ordinary List<T>
list.Insert(0, "A");
Assert.IsTrue(list.Count == 1);
list.Add("A");
Assert.IsTrue(list.Count == 2);
list.Insert(0, "A");
Assert.IsTrue(list.Count == 3);
// List END
}
}
}

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

@ -107,11 +107,27 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -107,11 +107,27 @@ namespace ICSharpCode.WpfDesign.XamlDom
/// </summary>
public static void Insert(Type collectionType, object collectionInstance, XamlPropertyValue newElement, int index)
{
collectionType.InvokeMember(
"Insert", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance,
null, collectionInstance,
new object[] { index, newElement.GetValueFor(null) },
CultureInfo.InvariantCulture);
object value = newElement.GetValueFor(null);
// Using IList, with possible Add instead of Insert, was primarily added as a workaround
// for a peculiarity (or bug) with collections inside System.Windows.Input namespace.
// See CollectionTests.InputCollectionsPeculiarityOrBug test method for details.
var list = collectionInstance as IList;
if (list != null) {
if (list.Count == index) {
list.Add(value);
}
else {
list.Insert(index, value);
}
}
else {
collectionType.InvokeMember(
"Insert", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance,
null, collectionInstance,
new object[] { index, value },
CultureInfo.InvariantCulture);
}
}
/// <summary>

Loading…
Cancel
Save