Browse Source

Removes namespace attributes from child nodes in the pasted snippet if they are already present in the root where the snippet is pasted.

Added a test "PasteCustomControlUsingMixedTypes" that failed before this fix.
pull/78/head
gumme 12 years ago
parent
commit
cd29a15e0d
  1. 63
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/EditOperationTests.cs
  2. 58
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTestHelper.cs
  3. 54
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs

63
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/EditOperationTests.cs

@ -4,6 +4,8 @@ @@ -4,6 +4,8 @@
using System;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using ICSharpCode.WpfDesign.Designer.Xaml;
using ICSharpCode.WpfDesign.XamlDom;
@ -14,6 +16,15 @@ namespace ICSharpCode.WpfDesign.Tests.Designer @@ -14,6 +16,15 @@ namespace ICSharpCode.WpfDesign.Tests.Designer
[TestFixture]
public class EditOperationTests : ModelTestHelper
{
protected override XamlLoadSettings CreateXamlLoadSettings()
{
var settings = base.CreateXamlLoadSettings();
settings.TypeFinder.RegisterAssembly(typeof(NamespaceTests).Assembly);
return settings;
}
Mutex mutex;
[TestFixtureSetUp]
@ -204,5 +215,57 @@ namespace ICSharpCode.WpfDesign.Tests.Designer @@ -204,5 +215,57 @@ namespace ICSharpCode.WpfDesign.Tests.Designer
Assert.IsNotNull(nameScope.FindName(_name + "_Copy3"));
Assert.IsNull(nameScope.FindName(_name + "_Copy4"));
}
[Test]
public void PasteCustomControlUsingMixedTypes()
{
DesignItem grid = CreateGridContextWithDesignSurface("<Button/>");
DesignItem myButton = grid.Services.Component.RegisterComponentForDesigner(new ICSharpCode.WpfDesign.Tests.Controls.CustomButton());
grid.Properties["Children"].CollectionElements.Add(myButton);
DesignItem extensionItem = grid.Services.Component.RegisterComponentForDesigner(new MyExtension());
extensionItem.Properties["MyProperty1"].SetValue(new Button());
myButton.Properties[ICSharpCode.WpfDesign.Tests.Controls.CustomButton.TagProperty].SetValue(extensionItem);
var xamlContext = grid.Context as XamlDesignContext;
Assert.IsNotNull(xamlContext);
xamlContext.XamlEditAction.Copy(new[] {myButton});
grid = CreateGridContextWithDesignSurface("<Button/>");
xamlContext = grid.Context as XamlDesignContext;
Assert.IsNotNull(xamlContext);
var selection = grid.Services.Selection;
selection.SetSelectedComponents(new[] {grid});
xamlContext.XamlEditAction.Paste();
string expectedXaml = "<Button />\n" +
"<sdtcontrols:CustomButton>\n" +
" <sdtcontrols:CustomButton.Tag>\n" +
" <Controls0:MyExtension>\n" +
" <Controls0:MyExtension.MyProperty1>\n" +
" <Button />\n" +
" </Controls0:MyExtension.MyProperty1>\n" +
" </Controls0:MyExtension>\n" +
" </sdtcontrols:CustomButton.Tag>\n" +
"</sdtcontrols:CustomButton>\n";
AssertGridDesignerOutput(expectedXaml, grid.Context,
"xmlns:Controls0=\"clr-namespace:ICSharpCode.WpfDesign.Tests.Designer;assembly=ICSharpCode.WpfDesign.Tests\"",
"xmlns:sdtcontrols=\"http://sharpdevelop.net/WpfDesign/Tests/Controls\"");
}
}
public class MyExtension : MarkupExtension
{
public MyExtension()
{
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return null;
}
public object MyProperty1 { get; set; }
}
}

58
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTestHelper.cs

@ -30,7 +30,7 @@ namespace ICSharpCode.WpfDesign.Tests.Designer @@ -30,7 +30,7 @@ namespace ICSharpCode.WpfDesign.Tests.Designer
protected XamlDesignContext CreateContext(string xaml)
{
log = new StringBuilder();
XamlDesignContext context = new XamlDesignContext(new XmlTextReader(new StringReader(xaml)), new XamlLoadSettings());
XamlDesignContext context = new XamlDesignContext(new XmlTextReader(new StringReader(xaml)), CreateXamlLoadSettings());
/*context.Services.Component.ComponentRegistered += delegate(object sender, DesignItemEventArgs e) {
log.AppendLine("Register " + ItemIdentity(e.Item));
};
@ -78,19 +78,7 @@ namespace ICSharpCode.WpfDesign.Tests.Designer @@ -78,19 +78,7 @@ namespace ICSharpCode.WpfDesign.Tests.Designer
expectedXaml.Replace("\r", "").Replace("\n", "\n ")
+ "\n</Canvas>";
StringWriter stringWriter = new StringWriter();
XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter);
xmlWriter.Formatting = Formatting.Indented;
context.Save(xmlWriter);
string actualXaml = stringWriter.ToString().Replace("\r", "");;
if (expectedXaml != actualXaml) {
Debug.WriteLine("expected xaml:");
Debug.WriteLine(expectedXaml);
Debug.WriteLine("actual xaml:");
Debug.WriteLine(actualXaml);
}
Assert.AreEqual(expectedXaml, actualXaml);
AssertDesignerOutput(expectedXaml, context);
}
protected DesignItem CreateGridContext(string xaml)
@ -107,16 +95,51 @@ namespace ICSharpCode.WpfDesign.Tests.Designer @@ -107,16 +95,51 @@ namespace ICSharpCode.WpfDesign.Tests.Designer
var surface = new DesignSurface();
var xamlWithGrid=@"<Grid xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" >
" + xaml + "</Grid>";
surface.LoadDesigner(new XmlTextReader(new StringReader(xamlWithGrid)), new XamlLoadSettings());
surface.LoadDesigner(new XmlTextReader(new StringReader(xamlWithGrid)), CreateXamlLoadSettings());
Assert.IsNotNull(surface.DesignContext.RootItem);
return surface.DesignContext.RootItem;
}
protected void AssertGridDesignerOutput(string expectedXaml, DesignContext context, params String[] additionalXmlns)
{
string gridStartTag = "<Grid xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"";
foreach(string ns in additionalXmlns) {
gridStartTag += " " + ns;
}
expectedXaml = gridStartTag + ">\n" + expectedXaml.Trim();
expectedXaml =
"<?xml version=\"1.0\" encoding=\"utf-16\"?>\n" +
expectedXaml.Replace("\r", "").Replace("\n", "\n ")
+ "\n</Grid>";
AssertDesignerOutput(expectedXaml, context);
}
static string ItemIdentity(DesignItem item)
{
return item.ComponentType.Name + " (" + item.GetHashCode() + ")";
}
protected void AssertDesignerOutput(string expectedXaml, DesignContext context)
{
StringWriter stringWriter = new StringWriter();
XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter);
xmlWriter.Formatting = Formatting.Indented;
context.Save(xmlWriter);
string actualXaml = stringWriter.ToString().Replace("\r", "");;
if (expectedXaml != actualXaml) {
Debug.WriteLine("expected xaml:");
Debug.WriteLine(expectedXaml);
Debug.WriteLine("actual xaml:");
Debug.WriteLine(actualXaml);
}
Assert.AreEqual(expectedXaml, actualXaml);
}
protected void AssertLog(string expectedLog)
{
expectedLog = expectedLog.Replace("\r", "");
@ -129,5 +152,10 @@ namespace ICSharpCode.WpfDesign.Tests.Designer @@ -129,5 +152,10 @@ namespace ICSharpCode.WpfDesign.Tests.Designer
}
Assert.AreEqual(expectedLog, actualLog);
}
protected virtual XamlLoadSettings CreateXamlLoadSettings()
{
return new XamlLoadSettings();
}
}
}

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

@ -605,6 +605,39 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -605,6 +605,39 @@ namespace ICSharpCode.WpfDesign.XamlDom
scope.OwnerDocument.GetTypeDescriptorContext(scope), valueText);
}
/// <summary>
/// Removes namespace attributes defined in the root from the specified node and all child nodes.
/// </summary>
static void RemoveRootNamespacesFromNodeAndChildNodes(XamlObject root, XmlNode node)
{
foreach (XmlNode childNode in node.ChildNodes) {
RemoveRootNamespacesFromNodeAndChildNodes(root, childNode);
}
if (node.Attributes != null) {
List<XmlAttribute> removeAttributes = new List<XmlAttribute>();
foreach (XmlAttribute attrib in node.Attributes) {
if (attrib.Name.StartsWith("xmlns:")) {
var rootPrefix = root.OwnerDocument.GetPrefixForNamespace(attrib.Value);
if (rootPrefix == null) {
//todo: check if we can add to root, (maybe same ns exists)
root.OwnerDocument.XmlDocument.Attributes.Append((XmlAttribute)attrib.CloneNode(true));
removeAttributes.Add(attrib);
}
else if (rootPrefix == attrib.Name.Substring("xmlns:".Length)) {
removeAttributes.Add(attrib);
}
}
else if (attrib.Name == "xmlns" && attrib.Value == XamlConstants.PresentationNamespace) {
removeAttributes.Add(attrib);
}
}
foreach (var removeAttribute in removeAttributes) {
node.Attributes.Remove(removeAttribute);
}
}
}
/// <summary>
/// Method use to parse a piece of Xaml.
/// </summary>
@ -625,25 +658,8 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -625,25 +658,8 @@ namespace ICSharpCode.WpfDesign.XamlDom
}
if(xmlnsAttribute!=null)
element.Attributes.Remove(xmlnsAttribute);
//Remove namespace Attributes defined in the Xaml Root from the Pasted Snippet!
List<XmlAttribute> removeAttributes = new List<XmlAttribute>();
foreach (XmlAttribute attrib in element.Attributes) {
if (attrib.Name.StartsWith("xmlns:")) {
var rootPrefix = root.OwnerDocument.GetPrefixForNamespace(attrib.Value);
if (rootPrefix == null) {
//todo: check if we can add to root, (maybe same ns exists)
root.OwnerDocument.XmlDocument.Attributes.Append((XmlAttribute)attrib.CloneNode(true));
removeAttributes.Add(attrib);
} else if (rootPrefix == attrib.Name.Substring(6)) {
removeAttributes.Add(attrib);
}
}
}
foreach (var removeAttribute in removeAttributes) {
element.Attributes.Remove(removeAttribute);
}
//end remove
RemoveRootNamespacesFromNodeAndChildNodes(root, element);
XamlParser parser = new XamlParser();
parser.settings = settings;

Loading…
Cancel
Save