From a1438e1e5efcc554b46113f82fc02c5e75eae31f Mon Sep 17 00:00:00 2001 From: gumme Date: Mon, 17 Jun 2013 11:49:31 +0200 Subject: [PATCH 01/41] Removing the optional "Extension" suffix from Markup Extension name if present. --- .../WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs index d9cb3b1aa6..2c94500487 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs @@ -353,7 +353,16 @@ namespace ICSharpCode.WpfDesign.XamlDom internal string GetNameForMarkupExtension() { - return XmlElement.Name; + string markupExtensionName = XmlElement.Name; + + // By convention a markup extension class name typically includes an "Extension" suffix. + // When you reference the markup extension in XAML the "Extension" suffix is optional. + // If present remove it to avoid bloating the XAML. + if (markupExtensionName.EndsWith("Extension", StringComparison.Ordinal)) { + markupExtensionName = markupExtensionName.Substring(0, markupExtensionName.Length - 9); + } + + return markupExtensionName; } } From e1ba7bc282a76c760a224b2df5c83290dca2e4a7 Mon Sep 17 00:00:00 2001 From: gumme Date: Mon, 17 Jun 2013 21:25:52 +0200 Subject: [PATCH 02/41] Made it possible to add resources to a ResourceDictionary through DesignItemProperty.CollectionElements. --- .../Project/Xaml/XamlDesignItem.cs | 5 +++++ .../Project/CollectionElementsCollection.cs | 4 +++- .../Project/CollectionSupport.cs | 15 +++++++++++++++ .../WpfDesign/WpfDesign/Project/DesignItem.cs | 5 +++++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignItem.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignItem.cs index 83ae4df39f..60b1d308b7 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignItem.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignItem.cs @@ -53,6 +53,11 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml set { this.Properties["Name"].SetValue(value); } } + public override string Key { + get { return XamlObject.GetXamlAttribute("Key"); } + set { XamlObject.SetXamlAttribute("Key", value); } + } + #if EventHandlerDebugging static int totalEventHandlerCount; #endif diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs index d37c2c82d1..f1ae0c21ba 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs @@ -51,7 +51,9 @@ namespace ICSharpCode.WpfDesign.XamlDom { XamlPropertyInfo info = property.propertyInfo; object collection = info.GetValue(property.ParentObject.Instance); - CollectionSupport.Insert(info.ReturnType, collection, item, index); + if (!CollectionSupport.TryInsert(info.ReturnType, collection, item, index)) { + CollectionSupport.AddToCollection(info.ReturnType, collection, item); + } item.ParentProperty = property; property.InsertNodeInCollection(item.GetNodeForCollection(), index); diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs index f41ca0f023..5907fce5bd 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs @@ -94,6 +94,21 @@ namespace ICSharpCode.WpfDesign.XamlDom CultureInfo.InvariantCulture); } + /// + /// Adds a value at the specified index in the collection. A return value indicates whether the Insert succeeded. + /// + /// True if the Insert succeeded, false if the collection type does not support Insert. + internal static bool TryInsert(Type collectionType, object collectionInstance, XamlPropertyValue newElement, int index) + { + try { + Insert(collectionType, collectionInstance, newElement, index); + } catch (MissingMethodException) { + return false; + } + + return true; + } + static readonly Type[] RemoveAtParameters = { typeof(int) }; /// diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs index ee93c82920..7ab86de912 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs @@ -64,6 +64,11 @@ namespace ICSharpCode.WpfDesign /// public abstract string Name { get; set; } + /// + /// Gets/Sets the value of the "x:Key" attribute on the design item. + /// + public abstract string Key { get; set; } + /// /// Is raised when the name of the design item changes. /// From 763f4d115bf0691c3cac19e54edd7cc81d4d837d Mon Sep 17 00:00:00 2001 From: gumme Date: Mon, 17 Jun 2013 21:29:52 +0200 Subject: [PATCH 03/41] Fixed bug; Only sets the inner text of an XML element if the element type defines a Content property. --- .../WpfDesign.XamlDom/Project/XamlDocument.cs | 5 ++++- .../WpfDesign.XamlDom/Project/XamlObject.cs | 20 +++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs index 5b62424e57..744617d8e7 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs @@ -169,9 +169,12 @@ namespace ICSharpCode.WpfDesign.XamlDom XmlElement xml = _xmlDoc.CreateElement(elementType.Name, GetNamespaceFor(elementType)); - if (hasStringConverter) { + if (hasStringConverter && + XamlObject.GetContentPropertyName(elementType) != null) + { xml.InnerText = c.ConvertToInvariantString(instance); } + return new XamlObject(this, xml, elementType, instance); } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs index 2c94500487..6c39539cc3 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs @@ -32,10 +32,7 @@ namespace ICSharpCode.WpfDesign.XamlDom this.elementType = elementType; this.instance = instance; - var contentAttrs = elementType.GetCustomAttributes(typeof(ContentPropertyAttribute), true) as ContentPropertyAttribute[]; - if (contentAttrs != null && contentAttrs.Length > 0) { - this.contentPropertyName = contentAttrs[0].Name; - } + this.contentPropertyName = GetContentPropertyName(elementType); ServiceProvider = new XamlObjectServiceProvider(this); CreateWrapper(); @@ -130,6 +127,21 @@ namespace ICSharpCode.WpfDesign.XamlDom return newElement; } + /// + /// Gets the name of the content property for the specified element type, or null if not available. + /// + /// The element type to get the content property name for. + /// The name of the content property for the specified element type, or null if not available. + internal static string GetContentPropertyName(Type elementType) + { + var contentAttrs = elementType.GetCustomAttributes(typeof(ContentPropertyAttribute), true) as ContentPropertyAttribute[]; + if (contentAttrs != null && contentAttrs.Length > 0) { + return contentAttrs[0].Name; + } + + return null; + } + internal override void AddNodeTo(XamlProperty property) { if (!UpdateXmlAttribute(true)) { From 990068d322e2728f955457295e392d4524ce91b4 Mon Sep 17 00:00:00 2001 From: gumme Date: Mon, 17 Jun 2013 22:13:58 +0200 Subject: [PATCH 04/41] Its WPF standard to use parent type name as prefix before the dot when declaring a property as XAML element, and NOT the name of the type that declares the property. --- .../WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs index 54293d7738..3e2a900f07 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs @@ -284,8 +284,8 @@ namespace ICSharpCode.WpfDesign.XamlDom if (collectionElements.Count == 0 && this.PropertyName != this.ParentObject.ContentPropertyName) { // we have to create the collection element _propertyElement = parentObject.OwnerDocument.XmlDocument.CreateElement( - this.PropertyTargetType.Name + "." + this.PropertyName, - parentObject.OwnerDocument.GetNamespaceFor(this.PropertyTargetType) + ParentObject.ElementType.Name + "." + this.PropertyName, + parentObject.OwnerDocument.GetNamespaceFor(ParentObject.ElementType) ); parentObject.XmlElement.AppendChild(_propertyElement); collection = _propertyElement; From 95583e9f3cf74074f89ae6b018c73f614f86f7bc Mon Sep 17 00:00:00 2001 From: gumme Date: Mon, 17 Jun 2013 23:12:43 +0200 Subject: [PATCH 05/41] Fixed so Resources are always first among child items. --- .../Project/XamlConstants.cs | 14 +++++++++++++ .../WpfDesign.XamlDom/Project/XamlProperty.cs | 21 ++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlConstants.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlConstants.cs index 95c48c552e..4ece7098f7 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlConstants.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlConstants.cs @@ -10,6 +10,8 @@ namespace ICSharpCode.WpfDesign.XamlDom /// public static class XamlConstants { + #region Namespaces + /// /// The namespace used to identify "xmlns". /// Value: "http://www.w3.org/2000/xmlns/" @@ -27,5 +29,17 @@ namespace ICSharpCode.WpfDesign.XamlDom /// Value: "http://schemas.microsoft.com/winfx/2006/xaml/presentation" /// public const string PresentationNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"; + + #endregion + + #region Common property names + + /// + /// The name of the Resources property. + /// Value: "Resources" + /// + public const string ResourcesPropertyName = "Resources"; + + #endregion } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs index 3e2a900f07..3f5ce64d05 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs @@ -24,6 +24,7 @@ namespace ICSharpCode.WpfDesign.XamlDom CollectionElementsCollection collectionElements; bool isCollection; + bool isResources; static readonly IList emptyCollectionElementsArray = new XamlPropertyValue[0]; @@ -49,6 +50,11 @@ namespace ICSharpCode.WpfDesign.XamlDom if (propertyInfo.IsCollection) { isCollection = true; collectionElements = new CollectionElementsCollection(this); + + if (propertyInfo.Name.Equals(XamlConstants.ResourcesPropertyName, StringComparison.Ordinal) && + propertyInfo.ReturnType == typeof(ResourceDictionary)) { + isResources = true; + } } } @@ -116,6 +122,13 @@ namespace ICSharpCode.WpfDesign.XamlDom set { SetPropertyValue(value); } } + /// + /// Gets if the property represents the FrameworkElement.Resources property that holds a locally-defined resource dictionary. + /// + public bool IsResources { + get { return isResources; } + } + /// /// Gets if the property is a collection property. /// @@ -287,7 +300,13 @@ namespace ICSharpCode.WpfDesign.XamlDom ParentObject.ElementType.Name + "." + this.PropertyName, parentObject.OwnerDocument.GetNamespaceFor(ParentObject.ElementType) ); - parentObject.XmlElement.AppendChild(_propertyElement); + + if (this.IsResources) { + parentObject.XmlElement.PrependChild(_propertyElement); + } else { + parentObject.XmlElement.AppendChild(_propertyElement); + } + collection = _propertyElement; } else { // this is the default collection From ad869adade1a989cd24ee58497a625dd28a640cf Mon Sep 17 00:00:00 2001 From: gumme Date: Thu, 20 Jun 2013 13:55:50 +0200 Subject: [PATCH 06/41] Added generated GlobalAssemblyInfo.cs to avoid the requirement to compile whole SharpDevelop solution before loose referenced projects can compile. --- .gitignore | 1 - src/Main/GlobalAssemblyInfo.cs | 36 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 src/Main/GlobalAssemblyInfo.cs diff --git a/.gitignore b/.gitignore index 5d9d573cc3..5a933b4dd5 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,6 @@ bin/ /src/Setup/SharpDevelop.Setup.wixproj.user /src/Main/ICSharpCode.SharpDevelop.Sda/ICSharpCode.SharpDevelop.Sda.dll.config /src/Main/StartUp/Project/SharpDevelop.exe.config -/src/Main/GlobalAssemblyInfo.cs /src/AddIns/Misc/UsageDataCollector/UsageDataCollector.AddIn/AnalyticsMonitor.AppProperties.cs /src/AddIns/Misc/PackageManagement/Packages/AvalonEdit/lib \ No newline at end of file diff --git a/src/Main/GlobalAssemblyInfo.cs b/src/Main/GlobalAssemblyInfo.cs new file mode 100644 index 0000000000..65349fb10d --- /dev/null +++ b/src/Main/GlobalAssemblyInfo.cs @@ -0,0 +1,36 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +// // +// DO NOT EDIT GlobalAssemblyInfo.cs, it is recreated using AssemblyInfo.template whenever // +// ICSharpCode.Core is compiled. // +// // +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// + +using System.Resources; +using System.Reflection; + +[assembly: System.Runtime.InteropServices.ComVisible(false)] +[assembly: AssemblyCompany("ic#code")] +[assembly: AssemblyProduct("SharpDevelop")] +[assembly: AssemblyCopyright("2000-2013 AlphaSierraPapa for the SharpDevelop Team")] +[assembly: AssemblyVersion(RevisionClass.Major + "." + RevisionClass.Minor + "." + RevisionClass.Build + "." + RevisionClass.Revision)] +[assembly: AssemblyInformationalVersion(RevisionClass.FullVersion + "-990068d3")] +[assembly: NeutralResourcesLanguage("en-US")] + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly", + Justification = "AssemblyInformationalVersion does not need to be a parsable version")] + +internal static class RevisionClass +{ + public const string Major = "4"; + public const string Minor = "3"; + public const string Build = "1"; + public const string Revision = "9451"; + public const string VersionName = null; // "" is not valid for no version name, you have to use null if you don't want a version name (eg "Beta 1") + + public const string FullVersion = Major + "." + Minor + "." + Build + ".9451"; +} From 8df438f7356bb4e72a3c159de68064fb1e8ca945 Mon Sep 17 00:00:00 2001 From: Tobias Gummesson Date: Thu, 4 Jul 2013 08:37:12 -0700 Subject: [PATCH 07/41] XML-namespaces for controls outside the default XML-namespace is now declared in the document root. As prefix for the XML-namespaces it primarily uses the value from XmlnsPrefixAttribute if it exists for the XML-namespace, otherwise a "ControlsX" name is generated, where X is the first free value. --- .../WpfDesign.XamlDom/Project/XamlDocument.cs | 56 ++++++++++++++++--- .../Project/XamlTypeFinder.cs | 48 ++++++++++++---- 2 files changed, 87 insertions(+), 17 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs index 744617d8e7..925dea9dbe 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs @@ -17,7 +17,9 @@ namespace ICSharpCode.WpfDesign.XamlDom XamlObject _rootElement; IServiceProvider _serviceProvider; - XamlTypeFinder _typeFinder; + XamlTypeFinder _typeFinder; + + int namespacePrefixCounter; internal XmlDocument XmlDocument { get { return _xmlDoc; } @@ -164,11 +166,13 @@ namespace ICSharpCode.WpfDesign.XamlDom bool hasStringConverter = c.CanConvertTo(ctx, typeof(string)) && c.CanConvertFrom(typeof(string)); if (forProperty != null && hasStringConverter) { return new XamlTextValue(this, c.ConvertToInvariantString(ctx, instance)); - } - - - XmlElement xml = _xmlDoc.CreateElement(elementType.Name, GetNamespaceFor(elementType)); - + } + + string ns = GetNamespaceFor(elementType); + string prefix = GetPrefixForNamespace(ns); + + XmlElement xml = _xmlDoc.CreateElement(prefix, elementType.Name, ns); + if (hasStringConverter && XamlObject.GetContentPropertyName(elementType) != null) { @@ -181,6 +185,44 @@ namespace ICSharpCode.WpfDesign.XamlDom internal string GetNamespaceFor(Type type) { return _typeFinder.GetXmlNamespaceFor(type.Assembly, type.Namespace); - } + } + + internal string GetPrefixForNamespace(string @namespace) + { + if (@namespace == XamlConstants.PresentationNamespace) + { + return null; + } + + string prefix = _xmlDoc.DocumentElement.GetPrefixOfNamespace(@namespace); + + if (String.IsNullOrEmpty(prefix)) + { + prefix = _typeFinder.GetPrefixForXmlNamespace(@namespace); + + string existingNamespaceForPrefix = null; + if (!String.IsNullOrEmpty(prefix)) + { + existingNamespaceForPrefix = _xmlDoc.DocumentElement.GetNamespaceOfPrefix(prefix); + } + + if (String.IsNullOrEmpty(prefix) || + !String.IsNullOrEmpty(existingNamespaceForPrefix) && + existingNamespaceForPrefix != @namespace) + { + do + { + prefix = "Controls" + namespacePrefixCounter++; + } while (!String.IsNullOrEmpty(_xmlDoc.DocumentElement.GetNamespaceOfPrefix(prefix))); + } + + string xmlnsPrefix = _xmlDoc.DocumentElement.GetPrefixOfNamespace(XamlConstants.XmlnsNamespace); + System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(xmlnsPrefix)); + + _xmlDoc.DocumentElement.SetAttribute(xmlnsPrefix + ":" + prefix, @namespace); + } + + return prefix; + } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTypeFinder.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTypeFinder.cs index 0abcbd0afd..9c4c24506d 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTypeFinder.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTypeFinder.cs @@ -42,11 +42,13 @@ namespace ICSharpCode.WpfDesign.XamlDom } sealed class XamlNamespace - { + { + internal readonly string XmlNamespacePrefix; internal readonly string XmlNamespace; - internal XamlNamespace(string xmlNamespace) - { + internal XamlNamespace(string xmlNamespacePrefix, string xmlNamespace) + { + this.XmlNamespacePrefix = xmlNamespacePrefix; this.XmlNamespace = xmlNamespace; } @@ -54,7 +56,7 @@ namespace ICSharpCode.WpfDesign.XamlDom internal XamlNamespace Clone() { - XamlNamespace copy = new XamlNamespace(this.XmlNamespace); + XamlNamespace copy = new XamlNamespace(this.XmlNamespacePrefix, this.XmlNamespace); // AssemblyNamespaceMapping is immutable copy.ClrNamespaces.AddRange(this.ClrNamespaces); return copy; @@ -107,7 +109,25 @@ namespace ICSharpCode.WpfDesign.XamlDom } else { return "clr-namespace:" + mapping.Namespace + ";assembly=" + mapping.Assembly.GetName().Name; } - } + } + + /// + /// Gets the prefix to use for the specified XML namespace, + /// or null if no suitable prefix could be found. + /// + public string GetPrefixForXmlNamespace(string xmlNamespace) + { + XamlNamespace ns; + + if (namespaces.TryGetValue(xmlNamespace, out ns)) + { + return ns.XmlNamespacePrefix; + } + else + { + return null; + } + } XamlNamespace ParseNamespace(string xmlNamespace) { @@ -127,7 +147,7 @@ namespace ICSharpCode.WpfDesign.XamlDom } assembly = name.Substring("assembly=".Length); } - XamlNamespace ns = new XamlNamespace(xmlNamespace); + XamlNamespace ns = new XamlNamespace(null, xmlNamespace); Assembly asm = LoadAssembly(assembly); if (asm != null) { AddMappingToNamespace(ns, new AssemblyNamespaceMapping(asm, namespaceName)); @@ -154,11 +174,19 @@ namespace ICSharpCode.WpfDesign.XamlDom public void RegisterAssembly(Assembly assembly) { if (assembly == null) - throw new ArgumentNullException("assembly"); + throw new ArgumentNullException("assembly"); + + Dictionary namespacePrefixes = new Dictionary(); + foreach (XmlnsPrefixAttribute xmlnsPrefix in assembly.GetCustomAttributes(typeof(XmlnsPrefixAttribute), true)) { + namespacePrefixes.Add(xmlnsPrefix.XmlNamespace, xmlnsPrefix.Prefix); + } + foreach (XmlnsDefinitionAttribute xmlnsDef in assembly.GetCustomAttributes(typeof(XmlnsDefinitionAttribute), true)) { - XamlNamespace ns; - if (!namespaces.TryGetValue(xmlnsDef.XmlNamespace, out ns)) { - ns = namespaces[xmlnsDef.XmlNamespace] = new XamlNamespace(xmlnsDef.XmlNamespace); + XamlNamespace ns; + if (!namespaces.TryGetValue(xmlnsDef.XmlNamespace, out ns)) { + string prefix; + namespacePrefixes.TryGetValue(xmlnsDef.XmlNamespace, out prefix); + ns = namespaces[xmlnsDef.XmlNamespace] = new XamlNamespace(prefix, xmlnsDef.XmlNamespace); } if (string.IsNullOrEmpty(xmlnsDef.AssemblyName)) { AddMappingToNamespace(ns, new AssemblyNamespaceMapping(assembly, xmlnsDef.ClrNamespace)); From 9af480c2ee7ac338be6c2c01a2e371e075fbca10 Mon Sep 17 00:00:00 2001 From: Tobias Gummesson Date: Fri, 5 Jul 2013 12:27:23 -0700 Subject: [PATCH 08/41] Fixed so nodes in the property grid gets DesignItemProperty instances that really represents attached properties when an attached property is used. When setting a property value as attribute, fixed so namespace prefix is only used for attached properties, and if no prefix is defined for a non-default namespace a new unique prefix is generated. --- .../Project/PropertyGrid/PropertyGrid.cs | 6 +-- .../WpfDesign.XamlDom/Project/XamlProperty.cs | 51 +++++++++++------- .../WpfDesign/Project/ExtensionMethods.cs | 53 +++++++++++++++++-- .../Project/PropertyGrid/PropertyNode.cs | 21 +++++++- 4 files changed, 104 insertions(+), 27 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyGrid.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyGrid.cs index 23248f7b26..426ac901e9 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyGrid.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyGrid.cs @@ -225,8 +225,8 @@ namespace ICSharpCode.WpfDesign.Designer.PropertyGrid } void AddNode(MemberDescriptor md) - { - var designProperties = SelectedItems.Select(item => item.Properties[md.Name]).ToArray(); + { + var designProperties = SelectedItems.Select(item => item.Properties.GetProperty(md)).ToArray(); if (!Metadata.IsBrowsable(designProperties[0])) return; PropertyNode node; @@ -252,7 +252,7 @@ namespace ICSharpCode.WpfDesign.Designer.PropertyGrid Category PickCategory(PropertyNode node) { if (Metadata.IsPopularProperty(node.FirstProperty)) return popularCategory; - if (node.FirstProperty.Name.Contains(".")) return attachedCategory; + if (node.FirstProperty.IsAttachedDependencyProperty()) return attachedCategory; var typeName = node.FirstProperty.DeclaringType.FullName; if (typeName.StartsWith("System.Windows.") || typeName.StartsWith("ICSharpCode.WpfDesign.Designer.Controls.")) return otherCategory; diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs index 3f5ce64d05..6e26a565cc 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs @@ -323,25 +323,38 @@ namespace ICSharpCode.WpfDesign.XamlDom // insert before specified index collection.InsertBefore(newChildNode, collectionElements[index].GetNodeForCollection()); } - } - - internal XmlAttribute SetAttribute(string value) - { - string ns = ParentObject.OwnerDocument.GetNamespaceFor(PropertyTargetType); - string name; - if (IsAttached) - name = PropertyTargetType.Name + "." + PropertyName; - else - name = PropertyName; - - var element = ParentObject.XmlElement; - if (string.IsNullOrEmpty(element.GetPrefixOfNamespace(ns))) { - element.SetAttribute(name, value); - return element.GetAttributeNode(name); - } else { - element.SetAttribute(name, ns, value); - return element.GetAttributeNode(name, ns); - } + } + + internal XmlAttribute SetAttribute(string value) + { + string name; + var element = ParentObject.XmlElement; + + if (IsAttached) + { + name = PropertyTargetType.Name + "." + PropertyName; + + string ns = ParentObject.OwnerDocument.GetNamespaceFor(PropertyTargetType); + string prefix = element.GetPrefixOfNamespace(ns); + + if (String.IsNullOrEmpty(prefix)) + { + prefix = ParentObject.OwnerDocument.GetPrefixForNamespace(ns); + } + + if (!string.IsNullOrEmpty(prefix)) + { + element.SetAttribute(name, ns, value); + return element.GetAttributeNode(name, ns); + } + } + else + { + name = PropertyName; + } + + element.SetAttribute(name, value); + return element.GetAttributeNode(name); } internal string GetNameForMarkupExtension() diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/ExtensionMethods.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/ExtensionMethods.cs index 69f9a54dfd..bd9df3670c 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/ExtensionMethods.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/ExtensionMethods.cs @@ -1,7 +1,8 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.ComponentModel; using System.Windows; namespace ICSharpCode.WpfDesign @@ -22,6 +23,52 @@ namespace ICSharpCode.WpfDesign Math.Round(rect.Width, PlacementInformation.BoundsPrecision), Math.Round(rect.Height, PlacementInformation.BoundsPrecision) ); + } + + /// + /// Gets the design item property for the specified member descriptor. + /// + public static DesignItemProperty GetProperty(this DesignItemPropertyCollection properties, MemberDescriptor md) + { + DesignItemProperty prop = null; + + var pd = md as PropertyDescriptor; + if (pd != null) + { + var dpd = DependencyPropertyDescriptor.FromProperty(pd); + if (dpd != null) + { + if (dpd.IsAttached) + { + prop = properties.GetAttachedProperty(dpd.DependencyProperty); + } + else + { + prop = properties.GetProperty(dpd.DependencyProperty); + } + } + } + + if (prop == null) + { + prop = properties[md.Name]; + } + + return prop; + } + + /// + /// Gets if the specified design item property represents an attached dependency property. + /// + public static bool IsAttachedDependencyProperty(this DesignItemProperty property) + { + if (property.DependencyProperty != null) + { + var dpd = DependencyPropertyDescriptor.FromProperty(property.DependencyProperty, property.DesignItem.ComponentType); + return dpd.IsAttached; + } + + return false; } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyGrid/PropertyNode.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyGrid/PropertyNode.cs index d212ead152..e3096a5907 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyGrid/PropertyNode.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyGrid/PropertyNode.cs @@ -34,7 +34,24 @@ namespace ICSharpCode.WpfDesign.PropertyGrid /// /// Gets the name of the property. /// - public string Name { get { return FirstProperty.Name; } } + public string Name + { + get + { + var dp = FirstProperty.DependencyProperty; + if (dp != null) + { + var dpd = DependencyPropertyDescriptor.FromProperty(dp, FirstProperty.DesignItem.ComponentType); + if (dpd.IsAttached) + { + // Will return the attached property name in the form of . + return dpd.Name; + } + } + + return FirstProperty.Name; + } + } /// /// Gets if this property node represents an event. @@ -366,7 +383,7 @@ namespace ICSharpCode.WpfDesign.PropertyGrid if (ValueItem != null) { var list = TypeHelper.GetAvailableProperties(ValueItem.Component) .OrderBy(d => d.Name) - .Select(d => new PropertyNode(new[] { ValueItem.Properties[d.Name] }, this)); + .Select(d => new PropertyNode(new[] { ValueItem.Properties.GetProperty(d) }, this)); foreach (var node in list) { if (Metadata.IsBrowsable(node.FirstProperty)) { From e5761c6d5c53d93c179570314251a77c1088a07b Mon Sep 17 00:00:00 2001 From: Tobias Gummesson Date: Mon, 8 Jul 2013 01:59:49 -0700 Subject: [PATCH 09/41] Removed Ignore attribute from SimpleLoadTests so the tests in the class will be executed. Made some modifications to XamlParser so it aligns with the official XamlReader and the SimpleLoadTests will pass. --- .../Tests/XamlDom/SimpleLoadTests.cs | 1 - .../WpfDesign.XamlDom/Project/XamlParser.cs | 28 ++++++------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/SimpleLoadTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/SimpleLoadTests.cs index 0928cc50fd..f21923390f 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/SimpleLoadTests.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/SimpleLoadTests.cs @@ -7,7 +7,6 @@ using NUnit.Framework; namespace ICSharpCode.WpfDesign.Tests.XamlDom { [TestFixture] - [Ignore("Broken on .NET 4")] public class SimpleLoadTests : TestHelper { [Test] diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs index 0d9abcf9cb..3c1288e2a0 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs @@ -265,7 +265,7 @@ namespace ICSharpCode.WpfDesign.XamlDom void ParseObjectContent(XamlObject obj, XmlElement element, XamlPropertyInfo defaultProperty, XamlTextValue initializeFromTextValueInsteadOfConstructor) { - XamlPropertyValue setDefaultValueTo = null; + bool isDefaultValueSet = false; object defaultPropertyValue = null; XamlProperty defaultCollectionProperty = null; @@ -290,11 +290,6 @@ namespace ICSharpCode.WpfDesign.XamlDom continue; if (ObjectChildElementIsPropertyElement(childElement)) { - // I don't know why the official XamlReader runs the property getter - // here, but let's try to imitate it as good as possible - if (defaultProperty != null && !defaultProperty.IsCollection) { - defaultProperty.GetValue(obj.Instance); - } ParseObjectChildElementAsPropertyElement(obj, childElement, defaultProperty, defaultPropertyValue); continue; } @@ -307,24 +302,17 @@ namespace ICSharpCode.WpfDesign.XamlDom defaultCollectionProperty.ParserAddCollectionElement(null, childValue); CollectionSupport.AddToCollection(defaultProperty.ReturnType, defaultPropertyValue, childValue); } else { - if (setDefaultValueTo != null) + if (defaultProperty == null) + throw new XamlLoadException("This element does not have a default value, cannot assign to it"); + + if (isDefaultValueSet) throw new XamlLoadException("default property may have only one value assigned"); - setDefaultValueTo = childValue; + + obj.AddProperty(new XamlProperty(obj, defaultProperty, childValue)); + isDefaultValueSet = true; } } } - - if (defaultProperty != null && !defaultProperty.IsCollection && !element.IsEmpty) { - // Runs even when defaultValueSet==false! - // Again, no idea why the official XamlReader does this. - defaultProperty.GetValue(obj.Instance); - } - if (setDefaultValueTo != null) { - if (defaultProperty == null) { - throw new XamlLoadException("This element does not have a default value, cannot assign to it"); - } - obj.AddProperty(new XamlProperty(obj, defaultProperty, setDefaultValueTo)); - } } int combinedNormalizedChildNodes; From 84053d7d848205d0fff2ca2b3bdbe9e29107c6ae Mon Sep 17 00:00:00 2001 From: Tobias Gummesson Date: Mon, 8 Jul 2013 02:37:11 -0700 Subject: [PATCH 10/41] Removed Ignore attribute from WhitespaceTests so the tests in the class will be executed. Made some modifications to XamlParser so it aligns with the official XamlReader and the WhitespaceTests will pass. --- .../Tests/XamlDom/WhitespaceTests.cs | 1 - .../WpfDesign.XamlDom/Project/XamlParser.cs | 15 +-------------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/WhitespaceTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/WhitespaceTests.cs index a1bfd201d0..71d3d4b6be 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/WhitespaceTests.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/WhitespaceTests.cs @@ -7,7 +7,6 @@ using NUnit.Framework; namespace ICSharpCode.WpfDesign.Tests.XamlDom { [TestFixture] - [Ignore("Broken on .NET 4")] public class WhitespaceTests : TestHelper { [Test] diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs index 3c1288e2a0..ecd0839c40 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs @@ -275,15 +275,6 @@ namespace ICSharpCode.WpfDesign.XamlDom } foreach (XmlNode childNode in GetNormalizedChildNodes(element)) { - - // I don't know why the official XamlReader runs the property getter - // here, but let's try to imitate it as good as possible - if (defaultProperty != null && !defaultProperty.IsCollection) { - for (; combinedNormalizedChildNodes > 0; combinedNormalizedChildNodes--) { - defaultProperty.GetValue(obj.Instance); - } - } - XmlElement childElement = childNode as XmlElement; if (childElement != null) { if (childElement.NamespaceURI == XamlConstants.XamlNamespace) @@ -314,9 +305,7 @@ namespace ICSharpCode.WpfDesign.XamlDom } } } - - int combinedNormalizedChildNodes; - + IEnumerable GetNormalizedChildNodes(XmlElement element) { XmlNode node = element.FirstChild; @@ -334,8 +323,6 @@ namespace ICSharpCode.WpfDesign.XamlDom && (node.NodeType == XmlNodeType.Text || node.NodeType == XmlNodeType.CDATA || node.NodeType == XmlNodeType.SignificantWhitespace)) { - combinedNormalizedChildNodes++; - if (text != null) text.Value += node.Value; else cData.Value += node.Value; XmlNode nodeToDelete = node; From 957b6f9e5dc6b27ee7773ff23c44974389393b16 Mon Sep 17 00:00:00 2001 From: Tobias Gummesson Date: Mon, 8 Jul 2013 11:40:53 -0700 Subject: [PATCH 11/41] If the ParentProperty is a collection the collection itself is the TargetObject (for example when adding Bindings to the MultiBinding.Bindings property). --- .../Project/XamlObjectServiceProvider.cs | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObjectServiceProvider.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObjectServiceProvider.cs index 523c477125..9bb120195f 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObjectServiceProvider.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObjectServiceProvider.cs @@ -56,14 +56,34 @@ namespace ICSharpCode.WpfDesign.XamlDom /// Gets the target object (the DependencyObject instance on which a property should be set) /// public object TargetObject { - get { return XamlObject.ParentProperty.ParentObject.Instance; } + get { + var parentProperty = XamlObject.ParentProperty; + + if (parentProperty == null) { + return null; + } + + if (parentProperty.IsCollection) { + return parentProperty.ValueOnInstance; + } + + return parentProperty.ParentObject.Instance; + } } /// /// Gets the target dependency property. /// public object TargetProperty { - get { return XamlObject.ParentProperty.DependencyProperty; } + get { + var parentProperty = XamlObject.ParentProperty; + + if (parentProperty == null) { + return null; + } + + return parentProperty.DependencyProperty; + } } #endregion From 295f62532f3be6cb42ed15128806afe08ca67a10 Mon Sep 17 00:00:00 2001 From: Tobias Gummesson Date: Wed, 10 Jul 2013 07:14:46 -0700 Subject: [PATCH 12/41] Fixed bug where list with errors in the designer was only updated if the document failed to load completely. --- .../WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs index d2110647d5..ba19940906 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs @@ -86,8 +86,8 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml parserSettings.CreateInstanceCallback = this.Services.ExtensionManager.CreateInstanceWithCustomInstanceFactory; parserSettings.ServiceProvider = this.Services; _doc = XamlParser.Parse(xamlReader, parserSettings); - if(_doc==null) - loadSettings.ReportErrors(xamlErrorService); + + loadSettings.ReportErrors(xamlErrorService); _rootItem = _componentService.RegisterXamlComponentRecursive(_doc.RootElement); From dbb326e801d51978af73323382eeef3b76527e4f Mon Sep 17 00:00:00 2001 From: Tobias Gummesson Date: Wed, 10 Jul 2013 08:33:30 -0700 Subject: [PATCH 13/41] The previous solution regarding XAML names expected all properties of type string named Name to represent a name in XAML namescope, and this caused trouble with types with a property named Name that did not represent a XAML name. In this case the value of the property tried to be registered as name to the namescope and this caused either the value to be occupied as name, or threw an exception if name already was taken or the value consisted of characters forbidden in XAML names causing the value to not be set at all. To solve this the value of a Name property is only registered to namescope if the property represents a XAML name (defined by RuntimeNamePropertyAttribute). Also added a Name property to XamlObject that always sets the name to x:Name attribute, but gets it from either x:Name or the property that represents the XAML name if it exists (both are valid places for name registration). Fixed a bug in XamlParser where x:Name value was not registered in its namescope. All other changes (for example changes in PropertyGrid/XamlDesignItem) was to support the Name fixes described above. --- .../Project/PropertyGrid/PropertyGrid.cs | 4 +- .../Project/Xaml/XamlDesignItem.cs | 8 +- .../Project/NameScopeHelper.cs | 48 +++++ .../Project/WpfDesign.XamlDom.csproj | 181 +++++++++--------- .../WpfDesign.XamlDom/Project/XamlObject.cs | 111 ++++++++++- .../WpfDesign.XamlDom/Project/XamlParser.cs | 11 +- .../WpfDesign.XamlDom/Project/XamlProperty.cs | 99 ++++------ 7 files changed, 304 insertions(+), 158 deletions(-) create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/NameScopeHelper.cs diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyGrid.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyGrid.cs index 426ac901e9..e448e42645 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyGrid.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyGrid.cs @@ -109,7 +109,7 @@ namespace ICSharpCode.WpfDesign.Designer.PropertyGrid try { if (string.IsNullOrEmpty(value)) { OldName = null; - SingleItem.Properties["Name"].Reset(); + SingleItem.Name = null; } else { OldName = SingleItem.Name; SingleItem.Name = value; @@ -225,7 +225,7 @@ namespace ICSharpCode.WpfDesign.Designer.PropertyGrid } void AddNode(MemberDescriptor md) - { + { var designProperties = SelectedItems.Select(item => item.Properties.GetProperty(md)).ToArray(); if (!Metadata.IsBrowsable(designProperties[0])) return; diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignItem.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignItem.cs index 60b1d308b7..a83eb70468 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignItem.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignItem.cs @@ -49,8 +49,8 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml } public override string Name { - get { return (string)this.Properties["Name"].ValueOnInstance; } - set { this.Properties["Name"].SetValue(value); } + get { return _xamlObject.Name; } + set { _xamlObject.Name = value; } } public override string Key { @@ -70,13 +70,13 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml #if EventHandlerDebugging Debug.WriteLine("Add event handler to " + this.ComponentType.Name + " (handler count=" + (++totalEventHandlerCount) + ")"); #endif - this.Properties["Name"].ValueChanged += value; + _xamlObject.NameChanged += value; } remove { #if EventHandlerDebugging Debug.WriteLine("Remove event handler from " + this.ComponentType.Name + " (handler count=" + (--totalEventHandlerCount) + ")"); #endif - this.Properties["Name"].ValueChanged -= value; + _xamlObject.NameChanged -= value; } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/NameScopeHelper.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/NameScopeHelper.cs new file mode 100644 index 0000000000..0ea8458426 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/NameScopeHelper.cs @@ -0,0 +1,48 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +using System; +using System.Diagnostics; +using System.Windows; +using System.Windows.Markup; + +namespace ICSharpCode.WpfDesign.XamlDom +{ + /// + /// Static methods to help with operations on Xaml elements. + /// + internal 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. + /// + /// The object where the name was changed. + /// The old name. + /// The new name. + public 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); + } + if (nameScope != null) { + if (oldName != null) { + try { + nameScope.UnregisterName(oldName); + } catch (Exception x) { + Debug.WriteLine(x.Message); + } + } + if (newName != null) { + nameScope.RegisterName(newName, namedObject.Instance); + } + break; + } + obj = obj.ParentObject; + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj index 7fc0d99da0..8348005b0d 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj @@ -1,91 +1,92 @@ - - - - {88DA149F-21B2-48AB-82C4-28FB6BDFD783} - Debug - AnyCPU - Library - ICSharpCode.WpfDesign.XamlDom - ICSharpCode.WpfDesign.XamlDom - False - False - 4 - false - True - ..\..\..\..\..\Main\ICSharpCode.SharpDevelop.snk - False - File - False - -Microsoft.Globalization#CA1303;-Microsoft.Performance#CA1800 - ..\..\..\..\..\..\AddIns\DisplayBindings\WpfDesign\ - ..\..\..\..\..\..\AddIns\DisplayBindings\WpfDesign\ICSharpCode.WpfDesign.XamlDom.xml - v4.0 - C:\Users\Daniel\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis - Client - - - true - Full - True - DEBUG;TRACE - False - - - False - None - False - TRACE - - - False - Auto - 4194304 - AnyCPU - 4096 - - - - - False - - - False - - - - 3.5 - - - - - - False - - - - - GlobalAssemblyInfo.cs - - - - - - - - - - - - - - - - - - - - - - - + + + + {88DA149F-21B2-48AB-82C4-28FB6BDFD783} + Debug + AnyCPU + Library + ICSharpCode.WpfDesign.XamlDom + ICSharpCode.WpfDesign.XamlDom + False + False + 4 + false + True + ..\..\..\..\..\Main\ICSharpCode.SharpDevelop.snk + False + File + False + -Microsoft.Globalization#CA1303;-Microsoft.Performance#CA1800 + ..\..\..\..\..\..\AddIns\DisplayBindings\WpfDesign\ + ..\..\..\..\..\..\AddIns\DisplayBindings\WpfDesign\ICSharpCode.WpfDesign.XamlDom.xml + v4.0 + C:\Users\Daniel\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis + Client + + + true + Full + True + DEBUG;TRACE + False + + + False + None + False + TRACE + + + False + Auto + 4194304 + AnyCPU + 4096 + + + + + False + + + False + + + + 3.5 + + + + + + False + + + + + GlobalAssemblyInfo.cs + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs index 6c39539cc3..b53ffebf99 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs @@ -23,7 +23,10 @@ namespace ICSharpCode.WpfDesign.XamlDom Type elementType; object instance; List properties = new List(); - + string contentPropertyName; + XamlProperty nameProperty; + string runtimeNameProperty; + /// For use by XamlParser only. internal XamlObject(XamlDocument document, XmlElement element, Type elementType, object instance) { @@ -36,6 +39,11 @@ namespace ICSharpCode.WpfDesign.XamlDom ServiceProvider = new XamlObjectServiceProvider(this); CreateWrapper(); + + var rnpAttrs = elementType.GetCustomAttributes(typeof(RuntimeNamePropertyAttribute), true) as RuntimeNamePropertyAttribute[]; + if (rnpAttrs != null && rnpAttrs.Length > 0 && !String.IsNullOrEmpty(rnpAttrs[0].Name)) { + runtimeNameProperty = rnpAttrs[0].Name; + } } /// For use by XamlParser only. @@ -170,6 +178,11 @@ namespace ICSharpCode.WpfDesign.XamlDom { UpdateXmlAttribute(false); UpdateMarkupExtensionChain(); + + if (property == NameProperty) { + if (NameChanged != null) + NameChanged(this, EventArgs.Empty); + } } void UpdateMarkupExtensionChain() @@ -250,8 +263,6 @@ namespace ICSharpCode.WpfDesign.XamlDom } } - string contentPropertyName; - /// /// Gets the name of the content property. /// @@ -261,6 +272,54 @@ namespace ICSharpCode.WpfDesign.XamlDom } } + /// + /// Gets which property name of the type maps to the XAML x:Name attribute. + /// + public string RuntimeNameProperty { + get { + return runtimeNameProperty; + } + } + + /// + /// Gets which property of the type maps to the XAML x:Name attribute. + /// + public XamlProperty NameProperty { + get { + if(nameProperty == null && runtimeNameProperty != null) + nameProperty = FindOrCreateProperty(runtimeNameProperty); + + return nameProperty; + } + } + + /// + /// Gets/Sets the name of this XamlObject. + /// + public string Name { + get + { + string name = GetXamlAttribute("Name"); + + if (String.IsNullOrEmpty(name)) { + if (NameProperty != null && NameProperty.IsSet) + name = (string)NameProperty.ValueOnInstance; + } + + if (name == String.Empty) + name = null; + + return name; + } + set + { + if (String.IsNullOrEmpty(value)) + this.SetXamlAttribute("Name", null); + else + this.SetXamlAttribute("Name", value); + } + } + /// /// Finds the specified property, or creates it if it doesn't exist. /// @@ -330,10 +389,51 @@ namespace ICSharpCode.WpfDesign.XamlDom /// public void SetXamlAttribute(string name, string value) { + XamlProperty runtimeNameProperty = null; + bool isNameChange = false; + + if (name == "Name") { + isNameChange = true; + string oldName = GetXamlAttribute("Name"); + + if (String.IsNullOrEmpty(oldName)) { + runtimeNameProperty = this.NameProperty; + if (runtimeNameProperty != null) { + if (runtimeNameProperty.IsSet) + oldName = (string)runtimeNameProperty.ValueOnInstance; + else + runtimeNameProperty = null; + } + } + + if (String.IsNullOrEmpty(oldName)) + oldName = null; + + NameScopeHelper.NameChanged(this, oldName, value); + } + if (value == null) element.RemoveAttribute(name, XamlConstants.XamlNamespace); else element.SetAttribute(name, XamlConstants.XamlNamespace, value); + + if (isNameChange) { + bool nameChangedAlreadyRaised = false; + if (runtimeNameProperty != null) { + var handler = new EventHandler((sender, e) => nameChangedAlreadyRaised = true); + this.NameChanged += handler; + + try { + runtimeNameProperty.Reset(); + } + finally { + this.NameChanged -= handler; + } + } + + if (NameChanged != null && !nameChangedAlreadyRaised) + NameChanged(this, EventArgs.Empty); + } } /// @@ -376,6 +476,11 @@ namespace ICSharpCode.WpfDesign.XamlDom return markupExtensionName; } + + /// + /// Is raised when the name of this XamlObject changes. + /// + public event EventHandler NameChanged; } abstract class MarkupExtensionWrapper diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs index ecd0839c40..3f6ead3e85 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs @@ -244,8 +244,17 @@ namespace ICSharpCode.WpfDesign.XamlDom if (attribute.Name == "xml:space") { continue; } - if (GetAttributeNamespace(attribute) == XamlConstants.XamlNamespace) + if (GetAttributeNamespace(attribute) == XamlConstants.XamlNamespace) { + if (attribute.LocalName == "Name") { + try { + NameScopeHelper.NameChanged(obj, null, attribute.Value); + } catch (Exception x) { + ReportException(x, attribute); + } + } continue; + } + ParseObjectAttribute(obj, attribute); } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs index 6e26a565cc..31e40f2a7c 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs @@ -323,38 +323,38 @@ namespace ICSharpCode.WpfDesign.XamlDom // insert before specified index collection.InsertBefore(newChildNode, collectionElements[index].GetNodeForCollection()); } - } - - internal XmlAttribute SetAttribute(string value) - { - string name; - var element = ParentObject.XmlElement; - - if (IsAttached) - { - name = PropertyTargetType.Name + "." + PropertyName; - - string ns = ParentObject.OwnerDocument.GetNamespaceFor(PropertyTargetType); - string prefix = element.GetPrefixOfNamespace(ns); - - if (String.IsNullOrEmpty(prefix)) - { - prefix = ParentObject.OwnerDocument.GetPrefixForNamespace(ns); - } - - if (!string.IsNullOrEmpty(prefix)) - { - element.SetAttribute(name, ns, value); - return element.GetAttributeNode(name, ns); - } - } - else - { - name = PropertyName; - } - - element.SetAttribute(name, value); - return element.GetAttributeNode(name); + } + + internal XmlAttribute SetAttribute(string value) + { + string name; + var element = ParentObject.XmlElement; + + if (IsAttached) + { + name = PropertyTargetType.Name + "." + PropertyName; + + string ns = ParentObject.OwnerDocument.GetNamespaceFor(PropertyTargetType); + string prefix = element.GetPrefixOfNamespace(ns); + + if (String.IsNullOrEmpty(prefix)) + { + prefix = ParentObject.OwnerDocument.GetPrefixForNamespace(ns); + } + + if (!string.IsNullOrEmpty(prefix)) + { + element.SetAttribute(name, ns, value); + return element.GetAttributeNode(name, ns); + } + } + else + { + name = PropertyName; + } + + element.SetAttribute(name, value); + return element.GetAttributeNode(name); } internal string GetNameForMarkupExtension() @@ -430,39 +430,22 @@ namespace ICSharpCode.WpfDesign.XamlDom void PossiblyNameChanged(XamlPropertyValue oldValue, XamlPropertyValue newValue) { - if (PropertyName == "Name" && ReturnType == typeof(string)) { - + if (ParentObject.RuntimeNameProperty != null && PropertyName == ParentObject.RuntimeNameProperty) { + + if (!String.IsNullOrEmpty(ParentObject.GetXamlAttribute("Name"))) { + throw new XamlLoadException("The property 'Name' is set more than once."); + } + string oldName = null; string newName = null; - + var oldTextValue = oldValue as XamlTextValue; if (oldTextValue != null) oldName = oldTextValue.Text; var newTextValue = newValue as XamlTextValue; if (newTextValue != null) newName = newTextValue.Text; - - var obj = ParentObject; - while (obj != null) { - var nameScope = obj.Instance as INameScope; - if (nameScope == null) { - if (obj.Instance is DependencyObject) - nameScope = NameScope.GetNameScope((DependencyObject)obj.Instance); - } - if (nameScope != null) { - if (oldName != null) { - try { - nameScope.UnregisterName(oldName); - } catch (Exception x) { - Debug.WriteLine(x.Message); - } - } - if (newName != null) { - nameScope.RegisterName(newName, ParentObject.Instance); - } - break; - } - obj = obj.ParentObject; - } + + NameScopeHelper.NameChanged(ParentObject, oldName, newName); } } From 006558f253769244bfd0141b75d8ce1a6c52b62c Mon Sep 17 00:00:00 2001 From: Tobias Gummesson Date: Thu, 11 Jul 2013 01:20:00 -0700 Subject: [PATCH 14/41] Throws a XamlLoadException with an error message describing the error instead of a NullReferenceException in the case where the document failed to load. --- .../WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs index ba19940906..336bf9719c 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs @@ -89,6 +89,15 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml loadSettings.ReportErrors(xamlErrorService); + if (_doc == null) { + string message; + if (xamlErrorService != null && xamlErrorService.Errors.Count > 0) + message = xamlErrorService.Errors[0].Message; + else + message = "Could not load document."; + throw new XamlLoadException(message); + } + _rootItem = _componentService.RegisterXamlComponentRecursive(_doc.RootElement); if(_rootItem!=null){ From c44f2918cdd26ec134dc94d117ae304fe04a6372 Mon Sep 17 00:00:00 2001 From: Tobias Gummesson Date: Thu, 11 Jul 2013 02:38:33 -0700 Subject: [PATCH 15/41] Sending in an empty string as namespaceURI when setting a value to an attribute that does not belong to a namespace, otherwise it will overwrite the value in another attribute with same name but in another namespace if it finds one. --- .../WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs index 31e40f2a7c..3071e4067c 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs @@ -353,7 +353,7 @@ namespace ICSharpCode.WpfDesign.XamlDom name = PropertyName; } - element.SetAttribute(name, value); + element.SetAttribute(name, String.Empty, value); return element.GetAttributeNode(name); } From 743a6dde9bc8ffccc39e0f395753f2e52aada638 Mon Sep 17 00:00:00 2001 From: Tobias Gummesson Date: Thu, 11 Jul 2013 12:37:29 -0700 Subject: [PATCH 16/41] Fixed missing namespace prefix on properties that is set as elements on types outside default XAML namespace. Fixing this in CreatePropertyElement method also fixed another bug for AddChildNodeToProperty method that was fixed earlier in InsertNodeInCollection method with commit comment as follows: "Its WPF standard to use parent type name as prefix before the dot when declaring a property as XAML element, and NOT the name of the type that declares the property." --- .../WpfDesign.XamlDom/Project/XamlProperty.cs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs index 3071e4067c..44127a76ef 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs @@ -267,6 +267,16 @@ namespace ICSharpCode.WpfDesign.XamlDom oldPropertyElement.ParentNode.RemoveChild(oldPropertyElement); } } + + XmlElement CreatePropertyElement() + { + string ns = parentObject.OwnerDocument.GetNamespaceFor(parentObject.ElementType); + return parentObject.OwnerDocument.XmlDocument.CreateElement( + parentObject.OwnerDocument.GetPrefixForNamespace(ns), + parentObject.ElementType.Name + "." + this.PropertyName, + ns + ); + } internal void AddChildNodeToProperty(XmlNode newChildNode) { @@ -280,10 +290,7 @@ namespace ICSharpCode.WpfDesign.XamlDom parentObject.XmlElement.InsertBefore(newChildNode, parentObject.XmlElement.FirstChild); return; } - _propertyElement = parentObject.OwnerDocument.XmlDocument.CreateElement( - this.PropertyTargetType.Name + "." + this.PropertyName, - parentObject.OwnerDocument.GetNamespaceFor(this.PropertyTargetType) - ); + _propertyElement = CreatePropertyElement(); parentObject.XmlElement.InsertBefore(_propertyElement, parentObject.XmlElement.FirstChild); } _propertyElement.AppendChild(newChildNode); @@ -296,10 +303,7 @@ namespace ICSharpCode.WpfDesign.XamlDom if (collection == null) { if (collectionElements.Count == 0 && this.PropertyName != this.ParentObject.ContentPropertyName) { // we have to create the collection element - _propertyElement = parentObject.OwnerDocument.XmlDocument.CreateElement( - ParentObject.ElementType.Name + "." + this.PropertyName, - parentObject.OwnerDocument.GetNamespaceFor(ParentObject.ElementType) - ); + _propertyElement = CreatePropertyElement(); if (this.IsResources) { parentObject.XmlElement.PrependChild(_propertyElement); From 899a0ee83571656d49a7295e77cb64d4691837ab Mon Sep 17 00:00:00 2001 From: gumme Date: Fri, 12 Jul 2013 09:48:07 +0200 Subject: [PATCH 17/41] Revert "Added generated GlobalAssemblyInfo.cs to avoid the requirement to compile whole SharpDevelop solution before loose referenced projects can compile." This reverts commit ad869adade1a989cd24ee58497a625dd28a640cf. --- .gitignore | 1 + src/Main/GlobalAssemblyInfo.cs | 36 ---------------------------------- 2 files changed, 1 insertion(+), 36 deletions(-) delete mode 100644 src/Main/GlobalAssemblyInfo.cs diff --git a/.gitignore b/.gitignore index 5a933b4dd5..5d9d573cc3 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ bin/ /src/Setup/SharpDevelop.Setup.wixproj.user /src/Main/ICSharpCode.SharpDevelop.Sda/ICSharpCode.SharpDevelop.Sda.dll.config /src/Main/StartUp/Project/SharpDevelop.exe.config +/src/Main/GlobalAssemblyInfo.cs /src/AddIns/Misc/UsageDataCollector/UsageDataCollector.AddIn/AnalyticsMonitor.AppProperties.cs /src/AddIns/Misc/PackageManagement/Packages/AvalonEdit/lib \ No newline at end of file diff --git a/src/Main/GlobalAssemblyInfo.cs b/src/Main/GlobalAssemblyInfo.cs deleted file mode 100644 index 65349fb10d..0000000000 --- a/src/Main/GlobalAssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -///////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////// -// // -// DO NOT EDIT GlobalAssemblyInfo.cs, it is recreated using AssemblyInfo.template whenever // -// ICSharpCode.Core is compiled. // -// // -///////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////// - -using System.Resources; -using System.Reflection; - -[assembly: System.Runtime.InteropServices.ComVisible(false)] -[assembly: AssemblyCompany("ic#code")] -[assembly: AssemblyProduct("SharpDevelop")] -[assembly: AssemblyCopyright("2000-2013 AlphaSierraPapa for the SharpDevelop Team")] -[assembly: AssemblyVersion(RevisionClass.Major + "." + RevisionClass.Minor + "." + RevisionClass.Build + "." + RevisionClass.Revision)] -[assembly: AssemblyInformationalVersion(RevisionClass.FullVersion + "-990068d3")] -[assembly: NeutralResourcesLanguage("en-US")] - -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly", - Justification = "AssemblyInformationalVersion does not need to be a parsable version")] - -internal static class RevisionClass -{ - public const string Major = "4"; - public const string Minor = "3"; - public const string Build = "1"; - public const string Revision = "9451"; - public const string VersionName = null; // "" is not valid for no version name, you have to use null if you don't want a version name (eg "Beta 1") - - public const string FullVersion = Major + "." + Minor + "." + Build + ".9451"; -} From 2af3fcb180dc1911d56dd3b8e7cd795a590bb801 Mon Sep 17 00:00:00 2001 From: Tobias Gummesson Date: Fri, 12 Jul 2013 04:32:54 -0700 Subject: [PATCH 18/41] Added default ReportErrors delegate that does nothing. This is necessary after the fix in commit 295f62532f3be6cb42ed15128806afe08ca67a10. Before that commit the ReportErrors was semi-optional; When loading was successful ReportErrors was never called (ReportErrors optional), but when document failed to be created a NullReferenceException was thrown because ReportErrors did not have a delegate. See also commit 006558f253769244bfd0141b75d8ce1a6c52b62c, that throws a more friendly exception than NullReferenceException when document fails to load. --- .../WpfDesign.Designer/Project/Xaml/XamlLoadSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlLoadSettings.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlLoadSettings.cs index 0f3030521f..eb59dd6070 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlLoadSettings.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlLoadSettings.cs @@ -16,7 +16,7 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml { public readonly ICollection DesignerAssemblies = new List(); public readonly List> CustomServiceRegisterFunctions = new List>(); - public Action ReportErrors; + public Action ReportErrors = (errorService) => { }; XamlTypeFinder typeFinder = XamlTypeFinder.CreateWpfTypeFinder(); public XamlTypeFinder TypeFinder { From bb4a661db2d9c17c0a1a75b2b2339ce7bc5a9dd4 Mon Sep 17 00:00:00 2001 From: Tobias Gummesson Date: Wed, 17 Jul 2013 09:33:22 -0700 Subject: [PATCH 19/41] Fixed so its possible to use MultiBinding and PriorityBinding on a DesignItemProperty and that it writes as expected to XAML. --- .../Tests/Designer/ModelTestHelper.cs | 8 ++- .../Tests/Designer/ModelTests.cs | 70 ++++++++++++++++--- .../Project/MarkupExtensionPrinter.cs | 5 ++ .../WpfDesign.XamlDom/Project/XamlObject.cs | 4 +- 4 files changed, 72 insertions(+), 15 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTestHelper.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTestHelper.cs index 0e6829c823..c4c61608f2 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTestHelper.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTestHelper.cs @@ -21,6 +21,8 @@ namespace ICSharpCode.WpfDesign.Tests.Designer /// public class ModelTestHelper { + public const string DesignerTestsNamespace = "clr-namespace:ICSharpCode.WpfDesign.Tests.Designer;assembly=ICSharpCode.WpfDesign.Tests"; + protected StringBuilder log; protected XamlDesignContext CreateContext(string xaml) @@ -40,7 +42,8 @@ namespace ICSharpCode.WpfDesign.Tests.Designer { XamlDesignContext context = CreateContext(@" + xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" + xmlns:t=""" + DesignerTestsNamespace + @"""> " + xaml + ""); Canvas canvas = (Canvas)context.RootItem.Component; DesignItem canvasChild = context.Services.Component.GetDesignItem(canvas.Children[0]); @@ -54,7 +57,8 @@ namespace ICSharpCode.WpfDesign.Tests.Designer expectedXaml = "\n" + ("\n" + expectedXaml.Trim()) + "xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" " + + "xmlns:t=\"" + DesignerTestsNamespace + "\">\n" + expectedXaml.Trim()) .Replace("\r", "").Replace("\n", "\n ") + "\n"; 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 1973bc3a33..887b7c03b3 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs @@ -1,17 +1,18 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) -using System; -using System.Text; -using System.IO; -using System.Xml; -using System.Diagnostics; -using System.Windows; -using System.Windows.Controls; -using NUnit.Framework; -using ICSharpCode.WpfDesign.Designer; -using ICSharpCode.WpfDesign.Designer.Xaml; -using ICSharpCode.WpfDesign.Designer.Services; +using System; +using System.Text; +using System.IO; +using System.Xml; +using System.Diagnostics; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using NUnit.Framework; +using ICSharpCode.WpfDesign.Designer; +using ICSharpCode.WpfDesign.Designer.Xaml; +using ICSharpCode.WpfDesign.Designer.Services; namespace ICSharpCode.WpfDesign.Tests.Designer { @@ -235,5 +236,52 @@ namespace ICSharpCode.WpfDesign.Tests.Designer "", canvas.Context); AssertLog(""); } + + [Test] + public void AddMultiBindingToTextBox() + { + DesignItem button = CreateCanvasContext("