diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/AssemblyInfo.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/AssemblyInfo.cs
new file mode 100644
index 0000000000..48e0b155e5
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/AssemblyInfo.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// Information about this assembly is defined by the following
+// attributes.
+//
+// change them to the information which is associated with the assembly
+// you compile.
+
+[assembly: AssemblyTitle("ICSharpCode.WpfDesign.XamlDom")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: CLSCompliant(true)]
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj
new file mode 100644
index 0000000000..e184ef871c
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj
@@ -0,0 +1,71 @@
+
+
+ {88DA149F-21B2-48AB-82C4-28FB6BDFD783}
+ Debug
+ AnyCPU
+ Library
+ ICSharpCode.WpfDesign.XamlDom
+ ICSharpCode.WpfDesign.XamlDom
+ bin\Debug\ICSharpCode.WpfDesign.XamlDom.xml
+ False
+ False
+ 4
+ false
+ True
+ ..\..\..\..\..\Main\ICSharpCode.SharpDevelop.snk
+ False
+ File
+ False
+ -Microsoft.Globalization#CA1303
+
+
+ bin\Debug\
+ true
+ Full
+ True
+ DEBUG;TRACE
+ False
+
+
+ bin\Release\
+ False
+ None
+ False
+ TRACE
+
+
+ False
+ Auto
+ 4194304
+ AnyCPU
+ 4096
+
+
+
+
+ False
+
+
+ False
+
+
+
+
+ False
+
+
+
+
+ GlobalAssemblyInfo.cs
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlConstants.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlConstants.cs
new file mode 100644
index 0000000000..a997b94bb9
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlConstants.cs
@@ -0,0 +1,36 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Collections.ObjectModel;
+
+namespace ICSharpCode.WpfDesign.XamlDom
+{
+ ///
+ /// Contains constants used by the Xaml parser.
+ ///
+ public static class XamlConstants
+ {
+ ///
+ /// The namespace used to identify "xmlns".
+ /// Value: "http://www.w3.org/2000/xmlns/"
+ ///
+ public const string XmlnsNamespace = "http://www.w3.org/2000/xmlns/";
+
+ ///
+ /// The namespace used for the XAML schema.
+ /// Value: "http://schemas.microsoft.com/winfx/2006/xaml"
+ ///
+ public const string XamlNamespace = "http://schemas.microsoft.com/winfx/2006/xaml";
+
+ ///
+ /// The namespace used for the WPF schema.
+ /// Value: "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ ///
+ public const string PresentationNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs
new file mode 100644
index 0000000000..d1f45bd20a
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs
@@ -0,0 +1,61 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Xml;
+
+namespace ICSharpCode.WpfDesign.XamlDom
+{
+ ///
+ /// Represents a .xaml document.
+ ///
+ public sealed class XamlDocument
+ {
+ XmlDocument _xmlDoc;
+ XamlObject _rootElement;
+
+ ///
+ /// Gets the root xaml object.
+ ///
+ public XamlObject RootElement {
+ get { return _rootElement; }
+ }
+
+ ///
+ /// Gets the object instance created by the root xaml object.
+ ///
+ public object RootInstance {
+ get { return (_rootElement != null) ? _rootElement.Instance : null; }
+ }
+
+ ///
+ /// Saves the xaml document into the .
+ ///
+ public void Save(XmlWriter writer)
+ {
+ if (writer == null)
+ throw new ArgumentNullException("writer");
+ _xmlDoc.Save(writer);
+ }
+
+ ///
+ /// Internal constructor, used by XamlParser.
+ ///
+ internal XamlDocument(XmlDocument xmlDoc)
+ {
+ this._xmlDoc = xmlDoc;
+ }
+
+ ///
+ /// Called by XamlParser to finish initializing the document.
+ ///
+ internal void ParseComplete(XamlObject rootElement)
+ {
+ this._rootElement = rootElement;
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlLoadException.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlLoadException.cs
new file mode 100644
index 0000000000..e81bee8c13
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlLoadException.cs
@@ -0,0 +1,48 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Runtime.Serialization;
+
+namespace ICSharpCode.WpfDesign.XamlDom
+{
+ ///
+ /// Exception class used for xaml loading failures.
+ ///
+ [Serializable]
+ public class XamlLoadException : Exception
+ {
+ ///
+ /// Create a new XamlLoadException instance.
+ ///
+ public XamlLoadException()
+ {
+ }
+
+ ///
+ /// Create a new XamlLoadException instance.
+ ///
+ public XamlLoadException(string message) : base(message)
+ {
+ }
+
+ ///
+ /// Create a new XamlLoadException instance.
+ ///
+ public XamlLoadException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+
+ ///
+ /// Create a new XamlLoadException instance.
+ ///
+ protected XamlLoadException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs
new file mode 100644
index 0000000000..e68a980f05
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs
@@ -0,0 +1,78 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Collections.Generic;
+using System.Xml;
+
+namespace ICSharpCode.WpfDesign.XamlDom
+{
+ ///
+ /// Represents a xaml object element.
+ ///
+ public sealed class XamlObject : XamlPropertyValue
+ {
+ XamlDocument document;
+ XmlElement element;
+ Type elementType;
+ object instance;
+ List properties = new List();
+
+ /// For use by XamlParser only.
+ internal XamlObject(XamlDocument document, XmlElement element, Type elementType, object instance)
+ {
+ this.document = document;
+ this.element = element;
+ this.elementType = elementType;
+ this.instance = instance;
+ }
+
+ /// For use by XamlParser only.
+ internal void AddProperty(XamlProperty property)
+ {
+ properties.Add(property);
+ }
+
+ #region XamlPropertyValue implementation
+ internal override object GetValueFor(XamlPropertyInfo targetProperty)
+ {
+ return instance;
+ }
+ #endregion
+
+ ///
+ /// Gets the XamlDocument where this XamlObject is declared in.
+ ///
+ public XamlDocument OwnerDocument {
+ get { return document; }
+ }
+
+ ///
+ /// Gets the instance created by this object element.
+ ///
+ public object Instance {
+ get { return instance; }
+ }
+
+ ///
+ /// Gets the type of this object element.
+ ///
+ public Type ElementType {
+ get { return elementType; }
+ }
+
+ ///
+ /// Gets a read-only collection of properties set on this XamlObject.
+ /// This includes both attribute and element properties.
+ ///
+ public IList Properties {
+ get {
+ return properties.AsReadOnly();
+ }
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs
new file mode 100644
index 0000000000..85c3a3d3e9
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs
@@ -0,0 +1,317 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+using System.Windows.Markup;
+using System.Xml;
+
+namespace ICSharpCode.WpfDesign.XamlDom
+{
+ ///
+ /// Class with static methods to parse XAML files and output a .
+ ///
+ public sealed class XamlParser
+ {
+ #region Static methods
+ ///
+ /// Parses a XAML document using a stream.
+ ///
+ public static XamlDocument Parse(Stream stream)
+ {
+ if (stream == null)
+ throw new ArgumentNullException("stream");
+ XmlDocument doc = new XmlDocument();
+ doc.Load(stream);
+ return Parse(doc);
+ }
+
+ ///
+ /// Parses a XAML document using a TextReader.
+ ///
+ public static XamlDocument Parse(TextReader reader)
+ {
+ if (reader == null)
+ throw new ArgumentNullException("reader");
+ XmlDocument doc = new XmlDocument();
+ doc.Load(reader);
+ return Parse(doc);
+ }
+
+ ///
+ /// Parses a XAML document using an XmlReader.
+ ///
+ public static XamlDocument Parse(XmlReader reader)
+ {
+ if (reader == null)
+ throw new ArgumentNullException("reader");
+ XmlDocument doc = new XmlDocument();
+ doc.Load(reader);
+ return Parse(doc);
+ }
+
+ ///
+ /// Creates a XAML document from an existing XmlDocument.
+ ///
+ internal static XamlDocument Parse(XmlDocument document)
+ {
+ if (document == null)
+ throw new ArgumentNullException("document");
+ XamlParser p = new XamlParser();
+ p.document = new XamlDocument(document);
+ p.document.ParseComplete(p.ParseObject(document.DocumentElement));
+ return p.document;
+ }
+ #endregion
+
+ XamlDocument document;
+ XamlTypeFinder typeFinder;
+
+ private XamlParser()
+ {
+ typeFinder = XamlTypeFinder.CreateWpfTypeFinder();
+ }
+
+ Type FindType(string namespaceUri, string localName)
+ {
+ Type elementType = typeFinder.GetType(namespaceUri, localName);
+ if (elementType == null)
+ throw new XamlLoadException("Cannot find type " + localName + " in " + namespaceUri);
+ return elementType;
+ }
+
+ static string GetAttributeNamespace(XmlAttribute attribute)
+ {
+ if (attribute.NamespaceURI.Length > 0)
+ return attribute.NamespaceURI;
+ else
+ return attribute.OwnerElement.NamespaceURI;
+ }
+
+ XmlSpace currentXmlSpace = XmlSpace.None;
+
+ XamlObject ParseObject(XmlElement element)
+ {
+ Type elementType = FindType(element.NamespaceURI, element.LocalName);
+ object instance = Activator.CreateInstance(elementType);
+ XamlObject obj = new XamlObject(document, element, elementType, instance);
+
+ ISupportInitialize iSupportInitializeInstance = instance as ISupportInitialize;
+ if (iSupportInitializeInstance != null) {
+ iSupportInitializeInstance.BeginInit();
+ }
+
+ XmlSpace oldXmlSpace = currentXmlSpace;
+ foreach (XmlAttribute attribute in element.Attributes) {
+ if (attribute.NamespaceURI == XamlConstants.XmlnsNamespace)
+ continue;
+ if (attribute.Name == "xml:space") {
+ currentXmlSpace = (XmlSpace)Enum.Parse(typeof(XmlSpace), attribute.Value, true);
+ continue;
+ }
+ if (GetAttributeNamespace(attribute) == XamlConstants.XamlNamespace)
+ continue;
+ ParseObjectAttribute(obj, attribute);
+ }
+
+ XamlPropertyInfo defaultProperty = GetDefaultProperty(elementType);
+ XamlPropertyValue setDefaultValueTo = null;
+ object defaultPropertyValue = null;
+ if (defaultProperty != null && defaultProperty.IsCollection && !element.IsEmpty) {
+ defaultPropertyValue = defaultProperty.GetValue(instance);
+ }
+
+ foreach (XmlNode childNode in element.ChildNodes) {
+ XmlElement childElement = childNode as XmlElement;
+ if (childElement != null) {
+ 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(instance);
+ }
+ ParseObjectChildElementAsPropertyElement(obj, childElement, defaultProperty, defaultPropertyValue);
+ continue;
+ }
+ }
+ XamlPropertyValue childValue = ParseValue(childNode);
+ if (childValue != null) {
+ if (defaultProperty != null && defaultProperty.IsCollection) {
+ defaultProperty.AddValue(defaultPropertyValue, childValue);
+ } else {
+ if (setDefaultValueTo != null)
+ throw new XamlLoadException("default property may have only one value assigned");
+ setDefaultValueTo = childValue;
+ }
+ }
+ }
+
+ if (defaultProperty != null && !defaultProperty.IsCollection && !element.IsEmpty)
+ {
+ // Runs even when defaultValueSet==false!
+ // Again, no idea why the official XamlReader does this.
+ defaultProperty.GetValue(instance);
+ }
+ if (setDefaultValueTo != null) {
+ if (defaultProperty == null) {
+ throw new XamlLoadException("This element does not have a default value, cannot assign to it");
+ }
+ defaultProperty.SetValue(instance, setDefaultValueTo.GetValueFor(defaultProperty));
+ }
+
+ if (iSupportInitializeInstance != null) {
+ iSupportInitializeInstance.EndInit();
+ }
+
+ currentXmlSpace = oldXmlSpace;
+
+ return obj;
+ }
+
+ XamlPropertyValue ParseValue(XmlNode childNode)
+ {
+ XmlText childText = childNode as XmlText;
+ if (childText != null) {
+ return new XamlTextValue(childText, currentXmlSpace);
+ }
+ XmlElement element = childNode as XmlElement;
+ if (element != null) {
+ return ParseObject(element);
+ }
+ return null;
+ }
+
+ static XamlPropertyInfo GetDefaultProperty(Type elementType)
+ {
+ foreach (ContentPropertyAttribute cpa in elementType.GetCustomAttributes(typeof(ContentPropertyAttribute), true)) {
+ return FindProperty(elementType, cpa.Name);
+ }
+ return null;
+ }
+
+ static XamlPropertyInfo FindProperty(Type elementType, string propertyName)
+ {
+ PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(elementType);
+ PropertyDescriptor propertyInfo = properties[propertyName];
+ if (propertyInfo == null) {
+ XamlPropertyInfo pi = TryFindAttachedProperty(elementType, propertyName);
+ if (pi != null) {
+ return pi;
+ } else {
+ throw new XamlLoadException("property " + propertyName + " not found");
+ }
+ }
+ return new XamlNormalPropertyInfo(propertyInfo);
+ }
+
+ static XamlPropertyInfo TryFindAttachedProperty(Type elementType, string propertyName)
+ {
+ MethodInfo getMethod = elementType.GetMethod("Get" + propertyName, BindingFlags.Public | BindingFlags.Static);
+ MethodInfo setMethod = elementType.GetMethod("Set" + propertyName, BindingFlags.Public | BindingFlags.Static);
+ if (getMethod != null && setMethod != null) {
+ return new XamlAttachedPropertyInfo(getMethod, setMethod);
+ }
+ return null;
+ }
+
+ static XamlPropertyInfo FindAttachedProperty(Type elementType, string propertyName)
+ {
+ XamlPropertyInfo pi = TryFindAttachedProperty(elementType, propertyName);
+ if (pi != null) {
+ return pi;
+ } else {
+ throw new XamlLoadException("attached property " + elementType.Name + "." + propertyName + " not found");
+ }
+ }
+
+ XamlPropertyInfo GetPropertyInfo(Type elementType, XmlAttribute attribute)
+ {
+ if (attribute.LocalName.Contains(".")) {
+ return GetPropertyInfo(elementType, GetAttributeNamespace(attribute), attribute.LocalName);
+ } else {
+ return FindProperty(elementType, attribute.LocalName);
+ }
+ }
+
+ XamlPropertyInfo GetPropertyInfo(Type elementType, string xmlNamespace, string localName)
+ {
+ string typeName, propertyName;
+ SplitQualifiedIdentifier(localName, out typeName, out propertyName);
+ Type propertyType = FindType(xmlNamespace, typeName);
+ if (elementType == propertyType || propertyType.IsAssignableFrom(elementType)) {
+ return FindProperty(propertyType, propertyName);
+ } else {
+ // This is an attached property
+ return FindAttachedProperty(propertyType, propertyName);
+ }
+ }
+
+ static void SplitQualifiedIdentifier(string qualifiedName, out string typeName, out string propertyName)
+ {
+ int pos = qualifiedName.IndexOf('.');
+ Debug.Assert(pos > 0);
+ typeName = qualifiedName.Substring(0, pos);
+ propertyName = qualifiedName.Substring(pos + 1);
+ }
+
+ void ParseObjectAttribute(XamlObject obj, XmlAttribute attribute)
+ {
+ XamlPropertyInfo propertyInfo = GetPropertyInfo(obj.ElementType, attribute);
+ XamlTextValue textValue = new XamlTextValue(attribute);
+ propertyInfo.SetValue(obj.Instance, textValue.GetValueFor(propertyInfo));
+ obj.AddProperty(new XamlProperty(obj, propertyInfo, textValue));
+ }
+
+ static bool ObjectChildElementIsPropertyElement(XmlElement element)
+ {
+ return element.LocalName.Contains(".");
+ }
+
+ void ParseObjectChildElementAsPropertyElement(XamlObject obj, XmlElement element, XamlPropertyInfo defaultProperty, object defaultPropertyValue)
+ {
+ Debug.Assert(element.LocalName.Contains("."));
+ // this is a element property syntax
+
+ XamlPropertyInfo propertyInfo = GetPropertyInfo(obj.ElementType, element.NamespaceURI, element.LocalName);
+ bool valueWasSet = false;
+
+ object collectionInstance = null;
+ if (propertyInfo.IsCollection) {
+ if (defaultProperty.FullyQualifiedName == propertyInfo.FullyQualifiedName) {
+ collectionInstance = defaultPropertyValue;
+ } else {
+ collectionInstance = propertyInfo.GetValue(obj.Instance);
+ }
+ }
+
+ XmlSpace oldXmlSpace = currentXmlSpace;
+ if (element.HasAttribute("xml:space")) {
+ currentXmlSpace = (XmlSpace)Enum.Parse(typeof(XmlSpace), element.GetAttribute("xml:space"), true);
+ }
+
+ foreach (XmlNode childNode in element.ChildNodes) {
+ XamlPropertyValue childValue = ParseValue(childNode);
+ if (childValue != null) {
+ if (propertyInfo.IsCollection) {
+ propertyInfo.AddValue(collectionInstance, childValue);
+ } else {
+ if (valueWasSet)
+ throw new XamlLoadException("non-collection property may have only one child element");
+ valueWasSet = true;
+ propertyInfo.SetValue(obj.Instance, childValue.GetValueFor(propertyInfo));
+ obj.AddProperty(new XamlProperty(obj, propertyInfo, childValue));
+ }
+ }
+ }
+
+ currentXmlSpace = oldXmlSpace;
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs
new file mode 100644
index 0000000000..01502f3975
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs
@@ -0,0 +1,139 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.ComponentModel;
+using System.Text;
+using System.Xml;
+
+namespace ICSharpCode.WpfDesign.XamlDom
+{
+ ///
+ /// Describes a property on a .
+ ///
+ public sealed class XamlProperty
+ {
+ XamlObject parentObject;
+ XamlPropertyInfo propertyInfo;
+ XamlPropertyValue propertyValue;
+
+ internal XamlProperty(XamlObject parentObject, XamlPropertyInfo propertyInfo, XamlPropertyValue propertyValue)
+ {
+ this.parentObject = parentObject;
+ this.propertyInfo = propertyInfo;
+ this.propertyValue = propertyValue;
+ }
+
+ ///
+ /// Gets the parent object for which this property was declared.
+ ///
+ public XamlObject ParentObject {
+ get { return parentObject; }
+ }
+
+ /*public bool IsAttributeSyntax {
+ get {
+ return attribute != null;
+ }
+ }
+
+ public bool IsElementSyntax {
+ get {
+ return element != null;
+ }
+ }
+
+ public bool IsImplicitDefaultProperty {
+ get {
+ return attribute == null && element == null;
+ }
+ }*/
+ }
+
+ ///
+ /// Used for the value of a .
+ /// Can be a or a .
+ ///
+ public abstract class XamlPropertyValue
+ {
+ internal abstract object GetValueFor(XamlPropertyInfo targetProperty);
+ }
+
+ ///
+ /// A textual value in a .xaml file.
+ ///
+ public sealed class XamlTextValue : XamlPropertyValue
+ {
+ XmlAttribute attribute;
+ XmlText textNode;
+ XmlSpace xmlSpace;
+
+ internal XamlTextValue(XmlAttribute attribute)
+ {
+ this.attribute = attribute;
+ }
+
+ internal XamlTextValue(XmlText textNode, XmlSpace xmlSpace)
+ {
+ this.xmlSpace = xmlSpace;
+ this.textNode = textNode;
+ }
+
+ ///
+ /// The text represented by the value.
+ ///
+ public string Text {
+ get {
+ if (attribute != null)
+ return attribute.Value;
+ else
+ return NormalizeWhitespace(textNode.Value);
+ }
+ set {
+ if (attribute != null)
+ attribute.Value = value;
+ else
+ textNode.Value = value;
+ }
+ }
+
+ string NormalizeWhitespace(string text)
+ {
+ if (xmlSpace == XmlSpace.Preserve) {
+ return text.Replace("\r", "");
+ }
+ StringBuilder b = new StringBuilder();
+ bool wasWhitespace = true;
+ foreach (char c in text) {
+ if (char.IsWhiteSpace(c)) {
+ if (!wasWhitespace) {
+ b.Append(' ');
+ }
+ wasWhitespace = true;
+ } else {
+ wasWhitespace = false;
+ b.Append(c);
+ }
+ }
+ if (b.Length > 0 && wasWhitespace)
+ b.Length -= 1;
+ return b.ToString();
+ }
+
+ internal override object GetValueFor(XamlPropertyInfo targetProperty)
+ {
+ if (targetProperty == null)
+ return this.Text;
+ TypeConverter converter = targetProperty.TypeConverter;
+ if (converter != null) {
+ return converter.ConvertFromInvariantString(this.Text);
+ } else {
+ return this.Text;
+ }
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlPropertyInfo.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlPropertyInfo.cs
new file mode 100644
index 0000000000..b374c27fd0
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlPropertyInfo.cs
@@ -0,0 +1,139 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Collections;
+using System.ComponentModel;
+using System.Globalization;
+using System.Reflection;
+using System.Windows.Markup;
+
+namespace ICSharpCode.WpfDesign.XamlDom
+{
+ ///
+ /// Represents a property assignable in XAML.
+ /// This can be a normal .NET property or an attached property.
+ ///
+ internal abstract class XamlPropertyInfo
+ {
+ public abstract object GetValue(object instance);
+ public abstract void SetValue(object instance, object value);
+ public abstract TypeConverter TypeConverter { get; }
+ public abstract string FullyQualifiedName { get; }
+ public abstract bool IsCollection { get; }
+ internal abstract void AddValue(object collectionInstance, XamlPropertyValue newElement);
+ }
+
+ internal sealed class XamlAttachedPropertyInfo : XamlPropertyInfo
+ {
+ MethodInfo _getMethod;
+ MethodInfo _setMethod;
+
+ public XamlAttachedPropertyInfo(MethodInfo getMethod, MethodInfo setMethod)
+ {
+ this._getMethod = getMethod;
+ this._setMethod = setMethod;
+ }
+
+ public override TypeConverter TypeConverter {
+ get {
+ return TypeDescriptor.GetConverter(_getMethod.ReturnType);
+ }
+ }
+
+ public override string FullyQualifiedName {
+ get {
+ return _getMethod.DeclaringType.FullName + "." + _getMethod.Name;
+ }
+ }
+
+ public override bool IsCollection {
+ get {
+ return false;
+ }
+ }
+
+ public override object GetValue(object instance)
+ {
+ return _getMethod.Invoke(null, new object[] { instance });
+ }
+
+ public override void SetValue(object instance, object value)
+ {
+ _setMethod.Invoke(null, new object[] { instance, value });
+ }
+
+ internal override void AddValue(object collectionInstance, XamlPropertyValue newElement)
+ {
+ throw new NotSupportedException();
+ }
+ }
+
+ internal sealed class XamlNormalPropertyInfo : XamlPropertyInfo
+ {
+ PropertyDescriptor _propertyDescriptor;
+
+ public XamlNormalPropertyInfo(PropertyDescriptor propertyDescriptor)
+ {
+ this._propertyDescriptor = propertyDescriptor;
+ }
+
+ public override object GetValue(object instance)
+ {
+ return _propertyDescriptor.GetValue(instance);
+ }
+
+ public override void SetValue(object instance, object value)
+ {
+ _propertyDescriptor.SetValue(instance, value);
+ }
+
+ public override TypeConverter TypeConverter {
+ get {
+ if (_propertyDescriptor.PropertyType == typeof(object))
+ return null;
+ else
+ return _propertyDescriptor.Converter;
+ }
+ }
+
+ public override string FullyQualifiedName {
+ get {
+ return _propertyDescriptor.ComponentType.FullName + "." + _propertyDescriptor.Name;
+ }
+ }
+
+ public override bool IsCollection {
+ get {
+ return CollectionSupport.IsCollectionType(_propertyDescriptor.PropertyType);
+ }
+ }
+
+ internal override void AddValue(object collectionInstance, XamlPropertyValue newElement)
+ {
+ _propertyDescriptor.PropertyType.InvokeMember(
+ "Add", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance,
+ null, collectionInstance,
+ new object[] {
+ newElement.GetValueFor(null)
+ }, CultureInfo.InvariantCulture);
+ }
+ }
+
+ static class CollectionSupport
+ {
+ public static bool IsCollectionType(Type type)
+ {
+ return typeof(IList).IsAssignableFrom(type)
+ || typeof(IDictionary).IsAssignableFrom(type)
+ || type.IsArray
+ || typeof(IAddChild).IsAssignableFrom(type);
+ }
+
+ //public static
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTypeFinder.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTypeFinder.cs
new file mode 100644
index 0000000000..596709fdb5
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTypeFinder.cs
@@ -0,0 +1,183 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Windows.Markup;
+
+namespace ICSharpCode.WpfDesign.XamlDom
+{
+ ///
+ /// Allows finding types in a set of assemblies.
+ ///
+ public class XamlTypeFinder : ICloneable
+ {
+ sealed class AssemblyNamespaceMapping
+ {
+ internal readonly Assembly Assembly;
+ internal readonly string Namespace;
+
+ internal AssemblyNamespaceMapping(Assembly assembly, string @namespace)
+ {
+ this.Assembly = assembly;
+ this.Namespace = @namespace;
+ }
+ }
+
+ sealed class XamlNamespace
+ {
+ internal List ClrNamespaces = new List();
+
+ internal XamlNamespace Clone()
+ {
+ XamlNamespace copy = new XamlNamespace();
+ // AssemblyNamespaceMapping is immutable
+ copy.ClrNamespaces.AddRange(this.ClrNamespaces);
+ return copy;
+ }
+ }
+
+ Dictionary namespaces = new Dictionary();
+
+ ///
+ /// Gets a type referenced in XAML.
+ ///
+ /// The XML namespace to use to look up the type.
+ /// This can be a registered namespace or a 'clr-namespace' value.
+ /// The local name of the type to find.
+ ///
+ /// The requested type, or null if it could not be found.
+ ///
+ public Type GetType(string xmlNamespace, string localName)
+ {
+ if (xmlNamespace == null)
+ throw new ArgumentNullException("xmlNamespace");
+ if (localName == null)
+ throw new ArgumentNullException("localName");
+ XamlNamespace ns;
+ if (!namespaces.TryGetValue(xmlNamespace, out ns)) {
+ if (xmlNamespace.StartsWith("clr-namespace:")) {
+ ns = namespaces[xmlNamespace] = ParseNamespace(xmlNamespace);
+ } else {
+ return null;
+ }
+ }
+ foreach (AssemblyNamespaceMapping mapping in ns.ClrNamespaces) {
+ Type type = mapping.Assembly.GetType(mapping.Namespace + "." + localName);
+ if (type != null)
+ return type;
+ }
+ return null;
+ }
+
+ XamlNamespace ParseNamespace(string name)
+ {
+ Debug.Assert(name.StartsWith("clr-namespace:"));
+ name = name.Substring("clr-namespace:".Length);
+ string namespaceName, assembly;
+ int pos = name.IndexOf(';');
+ if (pos < 0) {
+ namespaceName = name;
+ assembly = "";
+ } else {
+ namespaceName = name.Substring(0, pos);
+ name = name.Substring(pos + 1).Trim();
+ if (!name.StartsWith("assembly=")) {
+ throw new XamlLoadException("Expected: 'assembly='");
+ }
+ assembly = name.Substring("assembly=".Length);
+ }
+ XamlNamespace ns = new XamlNamespace();
+ ns.ClrNamespaces.Add(new AssemblyNamespaceMapping(LoadAssembly(assembly), namespaceName));
+ return ns;
+ }
+
+ ///
+ /// Registers XAML namespaces defined in the for lookup.
+ ///
+ public void RegisterAssembly(Assembly assembly)
+ {
+ if (assembly == null)
+ throw new ArgumentNullException("assembly");
+ foreach (XmlnsDefinitionAttribute xmlnsDef in assembly.GetCustomAttributes(typeof(XmlnsDefinitionAttribute), true)) {
+ XamlNamespace ns;
+ if (!namespaces.TryGetValue(xmlnsDef.XmlNamespace, out ns)) {
+ ns = namespaces[xmlnsDef.XmlNamespace] = new XamlNamespace();
+ }
+ if (string.IsNullOrEmpty(xmlnsDef.AssemblyName)) {
+ ns.ClrNamespaces.Add(new AssemblyNamespaceMapping(assembly, xmlnsDef.ClrNamespace));
+ } else {
+ Assembly asm = LoadAssembly(xmlnsDef.AssemblyName);
+ if (asm != null) {
+ ns.ClrNamespaces.Add(new AssemblyNamespaceMapping(asm, xmlnsDef.ClrNamespace));
+ }
+ }
+ }
+ }
+
+ ///
+ /// Load the assembly with the specified name.
+ /// You can override this method to implement custom assembly lookup.
+ ///
+ public virtual Assembly LoadAssembly(string name)
+ {
+ return Assembly.Load(name);
+ }
+
+ ///
+ /// Clones this XamlTypeFinder.
+ ///
+ public virtual XamlTypeFinder Clone()
+ {
+ XamlTypeFinder copy = new XamlTypeFinder();
+ copy.ImportFrom(this);
+ return copy;
+ }
+
+ ///
+ /// Import information from another XamlTypeFinder.
+ /// Use this if you override Clone().
+ ///
+ protected void ImportFrom(XamlTypeFinder source)
+ {
+ if (source == null)
+ throw new ArgumentNullException("source");
+ foreach (KeyValuePair pair in source.namespaces) {
+ this.namespaces.Add(pair.Key, pair.Value.Clone());
+ }
+ }
+
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
+
+ ///
+ /// Creates a new XamlTypeFinder where the WPF namespaces are registered.
+ ///
+ public static XamlTypeFinder CreateWpfTypeFinder()
+ {
+ return WpfTypeFinder.Instance.Clone();
+ }
+
+ static class WpfTypeFinder
+ {
+ internal static readonly XamlTypeFinder Instance;
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
+ static WpfTypeFinder()
+ {
+ Instance = new XamlTypeFinder();
+ Instance.RegisterAssembly(typeof(MarkupExtension).Assembly); // WindowsBase
+ Instance.RegisterAssembly(typeof(IAddChild).Assembly); // PresentationCore
+ Instance.RegisterAssembly(typeof(XamlReader).Assembly); // PresentationFramework
+ }
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/AssemblyInfo.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/AssemblyInfo.cs
new file mode 100644
index 0000000000..5c5ff4a347
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/AssemblyInfo.cs
@@ -0,0 +1,15 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// Information about this assembly is defined by the following
+// attributes.
+//
+// change them to the information which is associated with the assembly
+// you compile.
+
+[assembly: AssemblyTitle("WpfDesign.XamlDom.Tests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/ExampleClass.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/ExampleClass.cs
new file mode 100644
index 0000000000..763cf44ca3
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/ExampleClass.cs
@@ -0,0 +1,76 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.ComponentModel;
+using System.Windows.Markup;
+
+namespace ICSharpCode.WpfDesign.XamlDom.Tests
+{
+ [ContentProperty("StringProp")]
+ public class ExampleClass : ISupportInitialize
+ {
+ internal static int nextUniqueIndex;
+
+ string stringProp, otherProp, otherProp2;
+ int uniqueIndex = nextUniqueIndex++;
+
+ public ExampleClass()
+ {
+ TestHelperLog.Log("ctor" + Identity);
+ }
+
+ protected string Identity {
+ get {
+ return GetType().Name + " (" + uniqueIndex + ")";
+ }
+ }
+
+ void ISupportInitialize.BeginInit()
+ {
+ TestHelperLog.Log("BeginInit " + Identity);
+ }
+
+ void ISupportInitialize.EndInit()
+ {
+ TestHelperLog.Log("EndInit " + Identity);
+ }
+
+ public string StringProp {
+ get {
+ TestHelperLog.Log("StringProp.get " + Identity);
+ return stringProp;
+ }
+ set {
+ TestHelperLog.Log("StringProp.set to " + value + " - " + Identity);
+ stringProp = value;
+ }
+ }
+
+ public string OtherProp {
+ get {
+ TestHelperLog.Log("OtherProp.get " + Identity);
+ return otherProp;
+ }
+ set {
+ TestHelperLog.Log("OtherProp.set to " + value + " - " + Identity);
+ otherProp = value;
+ }
+ }
+
+ public string OtherProp2 {
+ get {
+ TestHelperLog.Log("OtherProp2.get " + Identity);
+ return otherProp2;
+ }
+ set {
+ TestHelperLog.Log("OtherProp2.set to " + value + " - " + Identity);
+ otherProp2 = value;
+ }
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/ExampleClassContainer.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/ExampleClassContainer.cs
new file mode 100644
index 0000000000..055fdd059d
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/ExampleClassContainer.cs
@@ -0,0 +1,27 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Windows.Markup;
+
+namespace ICSharpCode.WpfDesign.XamlDom.Tests
+{
+ [ContentProperty("List")]
+ public class ExampleClassContainer : ExampleClass
+ {
+ List list = new List();
+
+ public List List {
+ get {
+ TestHelperLog.Log("List.get " + Identity);
+ return list;
+ }
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/SamplesTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/SamplesTests.cs
new file mode 100644
index 0000000000..728e0473c0
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/SamplesTests.cs
@@ -0,0 +1,118 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using NUnit.Framework;
+
+namespace ICSharpCode.WpfDesign.XamlDom.Tests
+{
+ [TestFixture]
+ public class SamplesTests : TestHelper
+ {
+ ///
+ /// Non-trivial because of: InlineCollection wrapping a string
+ ///
+ [Test]
+ public void Intro1()
+ {
+ TestLoading(@"
+
+
+
+ Hello, World!
+
+
+");
+ }
+
+ ///
+ /// Non-trivial because of: found a bug in Control.Content handling
+ ///
+ [Test]
+ public void Intro2()
+ {
+ TestLoading(@"
+
+
+
+
+
+
+");
+ }
+
+ ///
+ /// Non-trivial because of: use of attached properties, units for width+height
+ ///
+ [Test]
+ public void Intro3()
+ {
+ TestLoading(@"
+
+
+ Some Text
+ Some text at the bottom of the page.
+ Some More Text
+
+
+
+
+
+ Some Text Below the Buttons
+
+
+
+");
+ }
+
+ ///
+ /// Using Hyperlinks
+ ///
+ [Test]
+ public void Intro4()
+ {
+ TestLoading(@"
+
+
+ Start Page
+
+ Go To Page 2
+
+
+");
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/SimpleLoadTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/SimpleLoadTests.cs
new file mode 100644
index 0000000000..b601835774
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/SimpleLoadTests.cs
@@ -0,0 +1,184 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using NUnit.Framework;
+using System;
+
+namespace ICSharpCode.WpfDesign.XamlDom.Tests
+{
+ [TestFixture]
+ public class SimpleLoadTests : TestHelper
+ {
+ [Test]
+ public void Window()
+ {
+ TestLoading(@"
+
+
+ ");
+ }
+
+ [Test]
+ public void WindowWithAttributes()
+ {
+ TestLoading(@"
+
+
+ ");
+ }
+
+ [Test]
+ public void WindowWithElementAttribute()
+ {
+ TestLoading(@"
+
+ 100
+
+ ");
+ }
+
+ [Test]
+ public void ExampleClassTest()
+ {
+ TestLoading(@"
+
+
+ ");
+ }
+
+ [Test]
+ public void ExampleClassWithStringPropAttribute()
+ {
+ TestLoading(@"
+
+
+ ");
+ }
+
+ [Test]
+ public void ExampleClassUseDefaultProperty()
+ {
+ TestLoading(@"
+
+ a test string
+
+ ");
+ }
+
+ [Test]
+ public void ExampleClassUseDefaultPropertyExplicitly()
+ {
+ TestLoading(@"
+
+
+ a test string
+
+
+ ");
+ }
+
+ [Test]
+ public void ExampleClassUseDefaultPropertyBeforeOtherPropertyElement()
+ {
+ TestLoading(@"
+
+ a test string
+
+ otherValue
+
+
+ ");
+ }
+
+ [Test]
+ public void ExampleClassUseDefaultPropertyAfterOtherPropertyElement()
+ {
+ TestLoading(@"
+
+
+ otherValue
+
+ a test string
+
+ ");
+ }
+
+ [Test]
+ public void ExampleClassUseDefaultPropertyBetweenOtherPropertyElement()
+ {
+ TestLoading(@"
+
+
+ otherValue
+
+ a test string
+
+ otherValue2
+
+
+ ");
+ }
+
+ [Test]
+ public void Container()
+ {
+ TestLoading(@"
+
+
+
+
+
+
+
+ ");
+ }
+
+ [Test]
+ public void ContainerImplicitList()
+ {
+ TestLoading(@"
+
+
+
+
+ ");
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/TestHelper.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/TestHelper.cs
new file mode 100644
index 0000000000..a4ff757af5
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/TestHelper.cs
@@ -0,0 +1,68 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Diagnostics;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Markup;
+using System.Xml;
+using System.IO;
+using NUnit.Framework;
+
+namespace ICSharpCode.WpfDesign.XamlDom.Tests
+{
+ public class TestHelper
+ {
+ public static T[] ToArray(IEnumerable e)
+ {
+ return new List(e).ToArray();
+ }
+
+ public static void TestLoading(string xaml)
+ {
+ Debug.WriteLine("Load using own XamlParser:");
+ ExampleClass.nextUniqueIndex = 0;
+ TestHelperLog.logBuilder = new StringBuilder();
+ XamlDocument doc = XamlParser.Parse(new XmlTextReader(new StringReader(xaml)));
+ Assert.IsNotNull(doc, "doc is null");
+ object ownResult = doc.RootInstance;
+ string ownLog = TestHelperLog.logBuilder.ToString();
+ Assert.IsNotNull(ownResult, "ownResult is null");
+
+ Debug.WriteLine("Load using builtin XamlReader:");
+ ExampleClass.nextUniqueIndex = 0;
+ TestHelperLog.logBuilder = new StringBuilder();
+ object officialResult = XamlReader.Load(new XmlTextReader(new StringReader(xaml)));
+ string officialLog = TestHelperLog.logBuilder.ToString();
+ Assert.IsNotNull(officialResult, "officialResult is null");
+
+ TestHelperLog.logBuilder = null;
+ // compare:
+ string officialSaved = XamlWriter.Save(officialResult);
+ string ownSaved = XamlWriter.Save(ownResult);
+
+ Assert.AreEqual(officialSaved, ownSaved);
+
+ // compare logs:
+ Assert.AreEqual(officialLog, ownLog);
+ }
+ }
+
+ internal static class TestHelperLog
+ {
+ internal static StringBuilder logBuilder;
+
+ internal static void Log(string text)
+ {
+ if (logBuilder != null) {
+ logBuilder.AppendLine(text);
+ Debug.WriteLine(text);
+ }
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/WhitespaceTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/WhitespaceTests.cs
new file mode 100644
index 0000000000..05cc598549
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/WhitespaceTests.cs
@@ -0,0 +1,100 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using NUnit.Framework;
+using System;
+
+namespace ICSharpCode.WpfDesign.XamlDom.Tests
+{
+ [TestFixture]
+ public class WhitespaceTests : TestHelper
+ {
+ [Test]
+ public void TrimSurroundingWhitespace()
+ {
+ TestLoading(@"
+
+
+ a test string
+
+
+ ");
+ }
+
+ [Test]
+ public void TrimConsecutiveWhitespace()
+ {
+ TestLoading(@"
+
+ a test string
+
+ ");
+ }
+
+ [Test]
+ public void ConvertLineFeedToSpace()
+ {
+ TestLoading(@"
+
+ a test
+ string
+
+ ");
+ }
+
+ [Test]
+ public void PreserveSurroundingWhitespace()
+ {
+ TestLoading(@"
+
+
+ a test string
+
+
+ ");
+ }
+
+ [Test]
+ public void PreserveConsecutiveWhitespace()
+ {
+ TestLoading(@"
+
+ a test string
+
+ ");
+ }
+
+ [Test]
+ public void PreserveLineFeed()
+ {
+ TestLoading(@"
+
+ a test
+ string
+
+ ");
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/WpfDesign.XamlDom.Tests.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/WpfDesign.XamlDom.Tests.csproj
new file mode 100644
index 0000000000..b80ecba420
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/WpfDesign.XamlDom.Tests.csproj
@@ -0,0 +1,63 @@
+
+
+ {BD62F5BC-115F-4339-8B5B-96C7A21DC67E}
+ Debug
+ AnyCPU
+ Library
+ ICSharpCode.WpfDesign.XamlDom.Tests
+ ICSharpCode.WpfDesign.XamlDom.Tests
+
+
+ bin\Debug\
+ True
+ Full
+ True
+ DEBUG;TRACE
+
+
+ bin\Release\
+ False
+ None
+ False
+ TRACE
+
+
+
+
+ ..\..\..\..\..\Tools\NUnit\nunit.framework.dll
+ False
+ True
+
+
+ False
+
+
+ False
+
+
+
+
+ False
+
+
+
+
+ GlobalAssemblyInfo.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {88DA149F-21B2-48AB-82C4-28FB6BDFD783}
+ WpfDesign.XamlDom
+
+
+
\ No newline at end of file
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/XamlTypeFinderTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/XamlTypeFinderTests.cs
new file mode 100644
index 0000000000..e7be09c162
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/XamlTypeFinderTests.cs
@@ -0,0 +1,64 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Windows.Markup;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace ICSharpCode.WpfDesign.XamlDom.Tests
+{
+ [TestFixture]
+ public class XamlTypeFinderTests : TestHelper
+ {
+ XamlTypeFinder typeFinder;
+
+ [SetUp]
+ public void FixtureSetUp()
+ {
+ typeFinder = XamlTypeFinder.CreateWpfTypeFinder();
+ }
+
+ [Test]
+ public void FindWindow()
+ {
+ Assert.AreEqual(typeof(Window),
+ typeFinder.GetType(XamlConstants.PresentationNamespace, "Window"));
+ }
+
+ [Test]
+ public void FindButton()
+ {
+ Assert.AreEqual(typeof(Button),
+ typeFinder.GetType(XamlConstants.PresentationNamespace, "Button"));
+ }
+
+ [Test]
+ public void FindBindingMarkupExtension()
+ {
+ Assert.AreEqual(typeof(StaticResourceExtension),
+ typeFinder.GetType(XamlConstants.PresentationNamespace, "StaticResourceExtension"));
+ }
+
+ [Test]
+ public void FindNullExtension()
+ {
+ Assert.AreEqual(typeof(NullExtension),
+ typeFinder.GetType(XamlConstants.XamlNamespace, "NullExtension"));
+ }
+
+ [Test]
+ public void FindExampleClass()
+ {
+ Assert.AreEqual(typeof(ExampleClass),
+ typeFinder.GetType("clr-namespace:ICSharpCode.WpfDesign.XamlDom.Tests;assembly=ICSharpCode.WpfDesign.XamlDom.Tests",
+ "ExampleClass"));
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/app.config b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/app.config
new file mode 100644
index 0000000000..e531f7e030
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/app.config
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.sln b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.sln
new file mode 100644
index 0000000000..3ce5a7c372
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.sln
@@ -0,0 +1,24 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+# SharpDevelop 2.1.0.2192
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign.XamlDom", "WpfDesign.XamlDom\Project\WpfDesign.XamlDom.csproj", "{88DA149F-21B2-48AB-82C4-28FB6BDFD783}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign.XamlDom.Tests", "WpfDesign.XamlDom\Tests\WpfDesign.XamlDom.Tests.csproj", "{BD62F5BC-115F-4339-8B5B-96C7A21DC67E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {88DA149F-21B2-48AB-82C4-28FB6BDFD783}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {88DA149F-21B2-48AB-82C4-28FB6BDFD783}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {88DA149F-21B2-48AB-82C4-28FB6BDFD783}.Release|Any CPU.Build.0 = Release|Any CPU
+ {88DA149F-21B2-48AB-82C4-28FB6BDFD783}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BD62F5BC-115F-4339-8B5B-96C7A21DC67E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BD62F5BC-115F-4339-8B5B-96C7A21DC67E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BD62F5BC-115F-4339-8B5B-96C7A21DC67E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BD62F5BC-115F-4339-8B5B-96C7A21DC67E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ EndGlobalSection
+EndGlobal