From fe0e8c045a34608099d701185a6ddadbcb32e04a Mon Sep 17 00:00:00 2001 From: gumme Date: Tue, 17 Sep 2013 12:09:01 +0200 Subject: [PATCH] Fixes the following in RegisterXamlComponentRecursive method (called for example on Paste): - Getting the correct namescope for RootItem (the INameScope case was not checked). - Clears the local namescope for the object if it exists, otherwise name changes will be registered in the local namespace instead of RootItem document namespace. - Only adds _Copy (or CopyX, where X is an integer) if the previous name did not already end with _Copy. This prevents names as "myname_Copy_Copy_Copy..." to occur when copying and pasting already copied elements. - Registers the new name to the RootItem namescope, only setting site.Name is not enough as its not yet a part of the RootItem document namescope. --- .../Project/Xaml/XamlComponentService.cs | 43 ++++++++++++------- .../Project/NameScopeHelper.cs | 39 +++++++++++++---- 2 files changed, 59 insertions(+), 23 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlComponentService.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlComponentService.cs index edbb41d40d..36ca45e8c2 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlComponentService.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlComponentService.cs @@ -90,24 +90,37 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml } if (_context.RootItem != null && !string.IsNullOrEmpty(site.Name)) { - var nameScope = _context.RootItem.Component as INameScope; - nameScope = NameScope.GetNameScope((DependencyObject) _context.RootItem.Component); - var fnd = nameScope.FindName(site.Name); - - if (fnd != null) { - string newNm = site.Name + "_Copy"; - fnd = nameScope.FindName(newNm); - if (fnd == null) - site.Name = newNm; - else { + var nameScope = NameScopeHelper.GetNameScopeFromObject(_context.RootItem.Component); + + if (nameScope != null) { + // The object will be a part of the RootItem namescope, remove local namescope if set + NameScopeHelper.ClearNameScopeProperty(obj.Instance); + + string newName = site.Name; + if (nameScope.FindName(newName) != null) { + int copyIndex = newName.LastIndexOf("_Copy", StringComparison.Ordinal); + if (copyIndex < 0) { + newName += "_Copy"; + } + else if (!newName.EndsWith("_Copy", StringComparison.Ordinal)) { + string copyEnd = newName.Substring(copyIndex + "_Copy".Length); + int copyEndValue; + if (Int32.TryParse(copyEnd, out copyEndValue)) + newName = newName.Remove(copyIndex + "_Copy".Length); + else + newName += "_Copy"; + } + int i = 1; - while (fnd != null) { - newNm = site.Name + "_Copy" + i; - fnd = nameScope.FindName(newNm); - i++; + string newNameTemplate = newName; + while (nameScope.FindName(newName) != null) { + newName = newNameTemplate + i++; } - site.Name = newNm; + + site.Name = newName; } + + nameScope.RegisterName(newName, obj.Instance); } } return site; diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/NameScopeHelper.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/NameScopeHelper.cs index aac3da5257..d77f74961e 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/NameScopeHelper.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/NameScopeHelper.cs @@ -10,7 +10,7 @@ namespace ICSharpCode.WpfDesign.XamlDom /// /// Static methods to help with operations on Xaml elements. /// - internal static class NameScopeHelper + public static class NameScopeHelper { /// /// Finds the XAML namescope for the specified object and uses it to unregister the old name and then register the new name. @@ -18,16 +18,11 @@ namespace ICSharpCode.WpfDesign.XamlDom /// The object where the name was changed. /// The old name. /// The new name. - public static void NameChanged(XamlObject namedObject, string oldName, string newName) + internal static void NameChanged(XamlObject namedObject, string oldName, string newName) { var obj = namedObject; while (obj != null) { - var nameScope = obj.Instance as INameScope; - if (nameScope == null) { - var depObj = obj.Instance as DependencyObject; - if (depObj != null) - nameScope = NameScope.GetNameScope(depObj); - } + var nameScope = GetNameScopeFromObject(obj.Instance); if (nameScope != null) { if (oldName != null) { try { @@ -52,5 +47,33 @@ namespace ICSharpCode.WpfDesign.XamlDom obj = obj.ParentObject; } } + + /// + /// Gets the XAML namescope for the specified object. + /// + /// The object to get the XAML namescope for. + /// A XAML namescope, as an instance. + public static INameScope GetNameScopeFromObject(object obj) + { + var nameScope = obj as INameScope; + if (nameScope == null) { + var depObj = obj as DependencyObject; + if (depObj != null) + nameScope = NameScope.GetNameScope(depObj); + } + + return nameScope; + } + + /// + /// Clears the if the object is a . + /// + /// The object to clear the on. + public static void ClearNameScopeProperty(object obj) + { + var depObj = obj as DependencyObject; + if (depObj != null) + depObj.ClearValue(NameScope.NameScopeProperty); + } } }