From a1438e1e5efcc554b46113f82fc02c5e75eae31f Mon Sep 17 00:00:00 2001 From: gumme Date: Mon, 17 Jun 2013 11:49:31 +0200 Subject: [PATCH 01/36] 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 d9cb3b1aa6e..2c945004873 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 @@ object ProvideValue() 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/36] 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 83ae4df39ff..60b1d308b76 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 @@ public override string Name { 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 d37c2c82d17..f1ae0c21ba1 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 @@ protected override void InsertItem(int index, XamlPropertyValue item) { 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 f41ca0f023b..5907fce5bd6 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 @@ public static void Insert(Type collectionType, object collectionInstance, XamlPr 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 ee93c82920b..7ab86de9129 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs @@ -64,6 +64,11 @@ public abstract class DesignItem : INotifyPropertyChanged /// 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/36] 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 5b62424e570..744617d8e77 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 @@ public XamlPropertyValue CreatePropertyValue(object instance, XamlProperty forPr 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 2c945004873..6c39539cc36 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 @@ internal XamlObject(XamlDocument document, XmlElement element, Type elementType, 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 @@ static XmlElement VirualAttachTo(XmlElement e, XmlElement target) 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/36] 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 54293d77381..3e2a900f079 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 @@ internal void InsertNodeInCollection(XmlNode newChildNode, int index) 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/36] 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 95c48c552ee..4ece7098f7a 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 @@ public static class XamlConstants /// 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 3e2a900f079..3f5ce64d050 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 @@ public sealed class XamlProperty CollectionElementsCollection collectionElements; bool isCollection; + bool isResources; static readonly IList emptyCollectionElementsArray = new XamlPropertyValue[0]; @@ -49,6 +50,11 @@ internal XamlProperty(XamlObject parentObject, XamlPropertyInfo propertyInfo) 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 @@ public XamlPropertyValue PropertyValue { 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 @@ internal void InsertNodeInCollection(XmlNode newChildNode, int index) 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/36] 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 5d9d573cc38..5a933b4dd59 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 00000000000..65349fb10d3 --- /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/36] 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 744617d8e77..925dea9dbee 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 @@ public sealed class XamlDocument XamlObject _rootElement; IServiceProvider _serviceProvider; - XamlTypeFinder _typeFinder; + XamlTypeFinder _typeFinder; + + int namespacePrefixCounter; internal XmlDocument XmlDocument { get { return _xmlDoc; } @@ -164,11 +166,13 @@ public XamlPropertyValue CreatePropertyValue(object instance, XamlProperty forPr 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 @@ public XamlPropertyValue CreatePropertyValue(object instance, XamlProperty forPr 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 0abcbd0afd2..9c4c24506d4 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 @@ public bool Equals(AssemblyNamespaceMapping other) } 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 @@ internal XamlNamespace(string xmlNamespace) 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 @@ public string GetXmlNamespaceFor(Assembly assembly, string @namespace) } 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 @@ XamlNamespace ParseNamespace(string xmlNamespace) } 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 @@ void AddMappingToNamespace(XamlNamespace ns, AssemblyNamespaceMapping mapping) 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/36] 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 23248f7b265..426ac901e97 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 @@ bool PassesFilter(string name) } 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 @@ void AddNode(MemberDescriptor md) 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 3f5ce64d050..6e26a565cc9 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 @@ internal void InsertNodeInCollection(XmlNode newChildNode, int index) // 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 69f9a54dfd7..bd9df3670cd 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 @@ public static Rect Round(this Rect rect) 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 d212ead152e..e3096a59078 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 @@ public class PropertyNode : INotifyPropertyChanged /// /// 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 @@ void UpdateChildren() 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/36] 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 0928cc50fd7..f21923390f7 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 @@ 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 0d9abcf9cbe..3c1288e2a0b 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 @@ XamlObject ParseObject(XmlElement element) 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 @@ void ParseObjectContent(XamlObject obj, XmlElement element, XamlPropertyInfo def 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 @@ void ParseObjectContent(XamlObject obj, XmlElement element, XamlPropertyInfo def 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/36] 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 a1bfd201d08..71d3d4b6be0 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 @@ 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 3c1288e2a0b..ecd0839c400 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 @@ void ParseObjectContent(XamlObject obj, XmlElement element, XamlPropertyInfo def } 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 @@ void ParseObjectContent(XamlObject obj, XmlElement element, XamlPropertyInfo def } } } - - int combinedNormalizedChildNodes; - + IEnumerable GetNormalizedChildNodes(XmlElement element) { XmlNode node = element.FirstChild; @@ -334,8 +323,6 @@ IEnumerable GetNormalizedChildNodes(XmlElement element) && (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/36] 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 523c477125b..9bb120195fd 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 @@ public object GetService(Type serviceType) /// 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/36] 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 d2110647d57..ba19940906f 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 @@ public XamlDesignContext(XmlReader xamlReader, XamlLoadSettings loadSettings) 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/36] 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 426ac901e97..e448e42645e 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 @@ public string Name { 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 @@ bool PassesFilter(string name) } 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 60b1d308b76..a83eb70468f 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 @@ public override Type ComponentType { } 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 @@ public override event EventHandler NameChanged { #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 00000000000..0ea84584266 --- /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 7fc0d99da00..8348005b0d1 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 6c39539cc36..b53ffebf990 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 @@ public sealed class XamlObject : XamlPropertyValue 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 @@ internal XamlObject(XamlDocument document, XmlElement element, Type elementType, 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 @@ internal void OnPropertyChanged(XamlProperty property) { UpdateXmlAttribute(false); UpdateMarkupExtensionChain(); + + if (property == NameProperty) { + if (NameChanged != null) + NameChanged(this, EventArgs.Empty); + } } void UpdateMarkupExtensionChain() @@ -250,8 +263,6 @@ public IList Properties { } } - string contentPropertyName; - /// /// Gets the name of the content property. /// @@ -261,6 +272,54 @@ public string ContentPropertyName { } } + /// + /// 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 @@ public string GetXamlAttribute(string name) /// 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 @@ internal string GetNameForMarkupExtension() 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 ecd0839c400..3f6ead3e85e 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 @@ XamlObject ParseObject(XmlElement element) 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 6e26a565cc9..31e40f2a7c0 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 @@ internal void InsertNodeInCollection(XmlNode newChildNode, int index) // 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 @@ public DependencyProperty DependencyProperty { 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/36] 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 ba19940906f..336bf9719c4 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 @@ public XamlDesignContext(XmlReader xamlReader, XamlLoadSettings loadSettings) 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/36] 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 31e40f2a7c0..3071e4067cf 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 @@ internal XmlAttribute SetAttribute(string value) 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/36] 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 3071e4067cf..44127a76efa 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 @@ internal void ParserSetPropertyElement(XmlElement propertyElement) 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 @@ internal void AddChildNodeToProperty(XmlNode newChildNode) 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 @@ internal void InsertNodeInCollection(XmlNode newChildNode, int index) 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/36] 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 5a933b4dd59..5d9d573cc38 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 65349fb10d3..00000000000 --- 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/36] 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 0f3030521f9..eb59dd60707 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 @@ public sealed class XamlLoadSettings { 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/36] 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 0e6829c823e..c4c61608f21 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 @@ protected DesignItem CreateCanvasContext(string xaml) { 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 @@ protected void AssertCanvasDesignerOutput(string expectedXaml, DesignContext con 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 1973bc3a33e..887b7c03b35 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 @@ public void ClearImplicitChildCollection() "", canvas.Context); AssertLog(""); } + + [Test] + public void AddMultiBindingToTextBox() + { + DesignItem button = CreateCanvasContext("