Browse Source

Start implementation of our .xaml loader.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2218 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 19 years ago
parent
commit
c974c6ac1c
  1. 17
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/AssemblyInfo.cs
  2. 71
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj
  3. 36
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlConstants.cs
  4. 61
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs
  5. 48
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlLoadException.cs
  6. 78
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs
  7. 317
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs
  8. 139
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs
  9. 139
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlPropertyInfo.cs
  10. 183
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTypeFinder.cs
  11. 15
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/AssemblyInfo.cs
  12. 76
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/ExampleClass.cs
  13. 27
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/ExampleClassContainer.cs
  14. 118
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/SamplesTests.cs
  15. 184
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/SimpleLoadTests.cs
  16. 68
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/TestHelper.cs
  17. 100
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/WhitespaceTests.cs
  18. 63
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/WpfDesign.XamlDom.Tests.csproj
  19. 64
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/XamlTypeFinderTests.cs
  20. 15
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/app.config
  21. 24
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.sln

17
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/AssemblyInfo.cs

@ -0,0 +1,17 @@ @@ -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)]

71
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{88DA149F-21B2-48AB-82C4-28FB6BDFD783}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<OutputType>Library</OutputType>
<RootNamespace>ICSharpCode.WpfDesign.XamlDom</RootNamespace>
<AssemblyName>ICSharpCode.WpfDesign.XamlDom</AssemblyName>
<DocumentationFile>bin\Debug\ICSharpCode.WpfDesign.XamlDom.xml</DocumentationFile>
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<NoStdLib>False</NoStdLib>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\..\..\..\Main\ICSharpCode.SharpDevelop.snk</AssemblyOriginatorKeyFile>
<DelaySign>False</DelaySign>
<AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode>
<RunCodeAnalysis>False</RunCodeAnalysis>
<CodeAnalysisRules>-Microsoft.Globalization#CA1303</CodeAnalysisRules>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<OutputPath>bin\Debug\</OutputPath>
<DebugSymbols>true</DebugSymbols>
<DebugType>Full</DebugType>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<Optimize>False</Optimize>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>bin\Release\</OutputPath>
<DebugSymbols>False</DebugSymbols>
<DebugType>None</DebugType>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
<RegisterForComInterop>False</RegisterForComInterop>
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
<BaseAddress>4194304</BaseAddress>
<PlatformTarget>AnyCPU</PlatformTarget>
<FileAlignment>4096</FileAlignment>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
<ItemGroup>
<Reference Include="PresentationCore">
<Private>False</Private>
</Reference>
<Reference Include="PresentationFramework">
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase">
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\..\..\..\Main\GlobalAssemblyInfo.cs">
<Link>GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="XamlConstants.cs" />
<Compile Include="XamlDocument.cs" />
<Compile Include="XamlLoadException.cs" />
<Compile Include="XamlObject.cs" />
<Compile Include="XamlParser.cs" />
<Compile Include="XamlProperty.cs" />
<Compile Include="XamlPropertyInfo.cs" />
<Compile Include="XamlTypeFinder.cs" />
</ItemGroup>
</Project>

36
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlConstants.cs

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.ObjectModel;
namespace ICSharpCode.WpfDesign.XamlDom
{
/// <summary>
/// Contains constants used by the Xaml parser.
/// </summary>
public static class XamlConstants
{
/// <summary>
/// The namespace used to identify "xmlns".
/// Value: "http://www.w3.org/2000/xmlns/"
/// </summary>
public const string XmlnsNamespace = "http://www.w3.org/2000/xmlns/";
/// <summary>
/// The namespace used for the XAML schema.
/// Value: "http://schemas.microsoft.com/winfx/2006/xaml"
/// </summary>
public const string XamlNamespace = "http://schemas.microsoft.com/winfx/2006/xaml";
/// <summary>
/// The namespace used for the WPF schema.
/// Value: "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
/// </summary>
public const string PresentationNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
}
}

61
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs

@ -0,0 +1,61 @@ @@ -0,0 +1,61 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Xml;
namespace ICSharpCode.WpfDesign.XamlDom
{
/// <summary>
/// Represents a .xaml document.
/// </summary>
public sealed class XamlDocument
{
XmlDocument _xmlDoc;
XamlObject _rootElement;
/// <summary>
/// Gets the root xaml object.
/// </summary>
public XamlObject RootElement {
get { return _rootElement; }
}
/// <summary>
/// Gets the object instance created by the root xaml object.
/// </summary>
public object RootInstance {
get { return (_rootElement != null) ? _rootElement.Instance : null; }
}
/// <summary>
/// Saves the xaml document into the <paramref name="writer"/>.
/// </summary>
public void Save(XmlWriter writer)
{
if (writer == null)
throw new ArgumentNullException("writer");
_xmlDoc.Save(writer);
}
/// <summary>
/// Internal constructor, used by XamlParser.
/// </summary>
internal XamlDocument(XmlDocument xmlDoc)
{
this._xmlDoc = xmlDoc;
}
/// <summary>
/// Called by XamlParser to finish initializing the document.
/// </summary>
internal void ParseComplete(XamlObject rootElement)
{
this._rootElement = rootElement;
}
}
}

48
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlLoadException.cs

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Runtime.Serialization;
namespace ICSharpCode.WpfDesign.XamlDom
{
/// <summary>
/// Exception class used for xaml loading failures.
/// </summary>
[Serializable]
public class XamlLoadException : Exception
{
/// <summary>
/// Create a new XamlLoadException instance.
/// </summary>
public XamlLoadException()
{
}
/// <summary>
/// Create a new XamlLoadException instance.
/// </summary>
public XamlLoadException(string message) : base(message)
{
}
/// <summary>
/// Create a new XamlLoadException instance.
/// </summary>
public XamlLoadException(string message, Exception innerException) : base(message, innerException)
{
}
/// <summary>
/// Create a new XamlLoadException instance.
/// </summary>
protected XamlLoadException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
}

78
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs

@ -0,0 +1,78 @@ @@ -0,0 +1,78 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.Xml;
namespace ICSharpCode.WpfDesign.XamlDom
{
/// <summary>
/// Represents a xaml object element.
/// </summary>
public sealed class XamlObject : XamlPropertyValue
{
XamlDocument document;
XmlElement element;
Type elementType;
object instance;
List<XamlProperty> properties = new List<XamlProperty>();
/// <summary>For use by XamlParser only.</summary>
internal XamlObject(XamlDocument document, XmlElement element, Type elementType, object instance)
{
this.document = document;
this.element = element;
this.elementType = elementType;
this.instance = instance;
}
/// <summary>For use by XamlParser only.</summary>
internal void AddProperty(XamlProperty property)
{
properties.Add(property);
}
#region XamlPropertyValue implementation
internal override object GetValueFor(XamlPropertyInfo targetProperty)
{
return instance;
}
#endregion
/// <summary>
/// Gets the XamlDocument where this XamlObject is declared in.
/// </summary>
public XamlDocument OwnerDocument {
get { return document; }
}
/// <summary>
/// Gets the instance created by this object element.
/// </summary>
public object Instance {
get { return instance; }
}
/// <summary>
/// Gets the type of this object element.
/// </summary>
public Type ElementType {
get { return elementType; }
}
/// <summary>
/// Gets a read-only collection of properties set on this XamlObject.
/// This includes both attribute and element properties.
/// </summary>
public IList<XamlProperty> Properties {
get {
return properties.AsReadOnly();
}
}
}
}

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

@ -0,0 +1,317 @@ @@ -0,0 +1,317 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
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
{
/// <summary>
/// Class with static methods to parse XAML files and output a <see cref="XamlDocument"/>.
/// </summary>
public sealed class XamlParser
{
#region Static methods
/// <summary>
/// Parses a XAML document using a stream.
/// </summary>
public static XamlDocument Parse(Stream stream)
{
if (stream == null)
throw new ArgumentNullException("stream");
XmlDocument doc = new XmlDocument();
doc.Load(stream);
return Parse(doc);
}
/// <summary>
/// Parses a XAML document using a TextReader.
/// </summary>
public static XamlDocument Parse(TextReader reader)
{
if (reader == null)
throw new ArgumentNullException("reader");
XmlDocument doc = new XmlDocument();
doc.Load(reader);
return Parse(doc);
}
/// <summary>
/// Parses a XAML document using an XmlReader.
/// </summary>
public static XamlDocument Parse(XmlReader reader)
{
if (reader == null)
throw new ArgumentNullException("reader");
XmlDocument doc = new XmlDocument();
doc.Load(reader);
return Parse(doc);
}
/// <summary>
/// Creates a XAML document from an existing XmlDocument.
/// </summary>
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;
}
}
}

139
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs

@ -0,0 +1,139 @@ @@ -0,0 +1,139 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.ComponentModel;
using System.Text;
using System.Xml;
namespace ICSharpCode.WpfDesign.XamlDom
{
/// <summary>
/// Describes a property on a <see cref="XamlObject"/>.
/// </summary>
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;
}
/// <summary>
/// Gets the parent object for which this property was declared.
/// </summary>
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;
}
}*/
}
/// <summary>
/// Used for the value of a <see cref="XamlProperty"/>.
/// Can be a <see cref="XamlTextValue"/> or a <see cref="XamlObject"/>.
/// </summary>
public abstract class XamlPropertyValue
{
internal abstract object GetValueFor(XamlPropertyInfo targetProperty);
}
/// <summary>
/// A textual value in a .xaml file.
/// </summary>
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;
}
/// <summary>
/// The text represented by the value.
/// </summary>
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;
}
}
}
}

139
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlPropertyInfo.cs

@ -0,0 +1,139 @@ @@ -0,0 +1,139 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections;
using System.ComponentModel;
using System.Globalization;
using System.Reflection;
using System.Windows.Markup;
namespace ICSharpCode.WpfDesign.XamlDom
{
/// <summary>
/// Represents a property assignable in XAML.
/// This can be a normal .NET property or an attached property.
/// </summary>
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
}
}

183
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTypeFinder.cs

@ -0,0 +1,183 @@ @@ -0,0 +1,183 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Windows.Markup;
namespace ICSharpCode.WpfDesign.XamlDom
{
/// <summary>
/// Allows finding types in a set of assemblies.
/// </summary>
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<AssemblyNamespaceMapping> ClrNamespaces = new List<AssemblyNamespaceMapping>();
internal XamlNamespace Clone()
{
XamlNamespace copy = new XamlNamespace();
// AssemblyNamespaceMapping is immutable
copy.ClrNamespaces.AddRange(this.ClrNamespaces);
return copy;
}
}
Dictionary<string, XamlNamespace> namespaces = new Dictionary<string, XamlNamespace>();
/// <summary>
/// Gets a type referenced in XAML.
/// </summary>
/// <param name="xmlNamespace">The XML namespace to use to look up the type.
/// This can be a registered namespace or a 'clr-namespace' value.</param>
/// <param name="localName">The local name of the type to find.</param>
/// <returns>
/// The requested type, or null if it could not be found.
/// </returns>
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;
}
/// <summary>
/// Registers XAML namespaces defined in the <paramref name="assembly"/> for lookup.
/// </summary>
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));
}
}
}
}
/// <summary>
/// Load the assembly with the specified name.
/// You can override this method to implement custom assembly lookup.
/// </summary>
public virtual Assembly LoadAssembly(string name)
{
return Assembly.Load(name);
}
/// <summary>
/// Clones this XamlTypeFinder.
/// </summary>
public virtual XamlTypeFinder Clone()
{
XamlTypeFinder copy = new XamlTypeFinder();
copy.ImportFrom(this);
return copy;
}
/// <summary>
/// Import information from another XamlTypeFinder.
/// Use this if you override Clone().
/// </summary>
protected void ImportFrom(XamlTypeFinder source)
{
if (source == null)
throw new ArgumentNullException("source");
foreach (KeyValuePair<string, XamlNamespace> pair in source.namespaces) {
this.namespaces.Add(pair.Key, pair.Value.Clone());
}
}
object ICloneable.Clone()
{
return this.Clone();
}
/// <summary>
/// Creates a new XamlTypeFinder where the WPF namespaces are registered.
/// </summary>
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
}
}
}
}

15
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/AssemblyInfo.cs

@ -0,0 +1,15 @@ @@ -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("")]

76
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/ExampleClass.cs

@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
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;
}
}
}
}

27
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/ExampleClassContainer.cs

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
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<ExampleClass> list = new List<ExampleClass>();
public List<ExampleClass> List {
get {
TestHelperLog.Log("List.get " + Identity);
return list;
}
}
}
}

118
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/SamplesTests.cs

@ -0,0 +1,118 @@ @@ -0,0 +1,118 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using NUnit.Framework;
namespace ICSharpCode.WpfDesign.XamlDom.Tests
{
[TestFixture]
public class SamplesTests : TestHelper
{
/// <summary>
/// Non-trivial because of: InlineCollection wrapping a string
/// </summary>
[Test]
public void Intro1()
{
TestLoading(@"
<Page
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
>
<StackPanel
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<TextBlock>
Hello, World!
</TextBlock>
</StackPanel>
</Page>");
}
/// <summary>
/// Non-trivial because of: found a bug in Control.Content handling
/// </summary>
[Test]
public void Intro2()
{
TestLoading(@"
<!--<SnippetSimpleLayout>-->
<StackPanel
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<Button HorizontalAlignment=""Left""
Width=""100""
Margin=""10,10,10,10"">Button 1</Button>
<Button HorizontalAlignment=""Left""
Width=""100""
Margin=""10,10,10,10"">Button 2</Button>
<Button HorizontalAlignment=""Left""
Width=""100""
Margin=""10,10,10,10"">Button 3</Button>
</StackPanel>
<!--</SnippetSimpleLayout>-->");
}
/// <summary>
/// Non-trivial because of: use of attached properties, units for width+height
/// </summary>
[Test]
public void Intro3()
{
TestLoading(@"
<Page
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<DockPanel
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<TextBlock Background=""LightBlue""
DockPanel.Dock=""Top"">Some Text</TextBlock>
<TextBlock DockPanel.Dock=""Bottom""
Background=""LightYellow"">Some text at the bottom of the page.</TextBlock>
<TextBlock DockPanel.Dock=""Left""
Background=""Lavender"">Some More Text</TextBlock>
<DockPanel Background=""Bisque"">
<StackPanel DockPanel.Dock=""Top"">
<Button HorizontalAlignment=""Left""
Height=""30px""
Width=""100px""
Margin=""10,10,10,10"">Button1</Button>
<Button HorizontalAlignment=""Left""
Height=""30px""
Width=""100px""
Margin=""10,10,10,10"">Button2</Button>
</StackPanel>
<TextBlock Background=""LightGreen"">Some Text Below the Buttons</TextBlock>
</DockPanel>
</DockPanel>
</Page>
");
}
/// <summary>
/// Using Hyperlinks
/// </summary>
[Test]
public void Intro4()
{
TestLoading(@"
<Page
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<StackPanel Background=""LightBlue"">
<TextBlock Margin=""10,10,10,10"">Start Page</TextBlock>
<TextBlock HorizontalAlignment=""Left""
Margin=""10,10,10,10"">
<Hyperlink NavigateUri=""Page2.xaml"">Go To Page 2</Hyperlink>
</TextBlock>
</StackPanel>
</Page>");
}
}
}

184
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/SimpleLoadTests.cs

@ -0,0 +1,184 @@ @@ -0,0 +1,184 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using NUnit.Framework;
using System;
namespace ICSharpCode.WpfDesign.XamlDom.Tests
{
[TestFixture]
public class SimpleLoadTests : TestHelper
{
[Test]
public void Window()
{
TestLoading(@"
<Window
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
</Window>
");
}
[Test]
public void WindowWithAttributes()
{
TestLoading(@"
<Window
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
Width=""300"" Height=""400"">
</Window>
");
}
[Test]
public void WindowWithElementAttribute()
{
TestLoading(@"
<Window
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<Window.Height>100</Window.Height>
</Window>
");
}
[Test]
public void ExampleClassTest()
{
TestLoading(@"
<t:ExampleClass
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:t=""clr-namespace:ICSharpCode.WpfDesign.XamlDom.Tests;assembly=ICSharpCode.WpfDesign.XamlDom.Tests""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
</t:ExampleClass>
");
}
[Test]
public void ExampleClassWithStringPropAttribute()
{
TestLoading(@"
<t:ExampleClass
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:t=""clr-namespace:ICSharpCode.WpfDesign.XamlDom.Tests;assembly=ICSharpCode.WpfDesign.XamlDom.Tests""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
StringProp=""a test string"">
</t:ExampleClass>
");
}
[Test]
public void ExampleClassUseDefaultProperty()
{
TestLoading(@"
<t:ExampleClass
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:t=""clr-namespace:ICSharpCode.WpfDesign.XamlDom.Tests;assembly=ICSharpCode.WpfDesign.XamlDom.Tests""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
a test string
</t:ExampleClass>
");
}
[Test]
public void ExampleClassUseDefaultPropertyExplicitly()
{
TestLoading(@"
<t:ExampleClass
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:t=""clr-namespace:ICSharpCode.WpfDesign.XamlDom.Tests;assembly=ICSharpCode.WpfDesign.XamlDom.Tests""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<t:ExampleClass.StringProp>
a test string
</t:ExampleClass.StringProp>
</t:ExampleClass>
");
}
[Test]
public void ExampleClassUseDefaultPropertyBeforeOtherPropertyElement()
{
TestLoading(@"
<t:ExampleClass
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:t=""clr-namespace:ICSharpCode.WpfDesign.XamlDom.Tests;assembly=ICSharpCode.WpfDesign.XamlDom.Tests""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
a test string
<t:ExampleClass.OtherProp>
otherValue
</t:ExampleClass.OtherProp>
</t:ExampleClass>
");
}
[Test]
public void ExampleClassUseDefaultPropertyAfterOtherPropertyElement()
{
TestLoading(@"
<t:ExampleClass
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:t=""clr-namespace:ICSharpCode.WpfDesign.XamlDom.Tests;assembly=ICSharpCode.WpfDesign.XamlDom.Tests""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<t:ExampleClass.OtherProp>
otherValue
</t:ExampleClass.OtherProp>
a test string
</t:ExampleClass>
");
}
[Test]
public void ExampleClassUseDefaultPropertyBetweenOtherPropertyElement()
{
TestLoading(@"
<t:ExampleClass
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:t=""clr-namespace:ICSharpCode.WpfDesign.XamlDom.Tests;assembly=ICSharpCode.WpfDesign.XamlDom.Tests""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<t:ExampleClass.OtherProp>
otherValue
</t:ExampleClass.OtherProp>
a test string
<t:ExampleClass.OtherProp2>
otherValue2
</t:ExampleClass.OtherProp2>
</t:ExampleClass>
");
}
[Test]
public void Container()
{
TestLoading(@"
<ExampleClassContainer
xmlns=""clr-namespace:ICSharpCode.WpfDesign.XamlDom.Tests;assembly=ICSharpCode.WpfDesign.XamlDom.Tests""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<ExampleClassContainer.List>
<ExampleClass OtherProp=""a""> </ExampleClass>
<ExampleClass OtherProp=""b"" />
<ExampleClass OtherProp=""c"" />
</ExampleClassContainer.List>
</ExampleClassContainer>
");
}
[Test]
public void ContainerImplicitList()
{
TestLoading(@"
<ExampleClassContainer
xmlns=""clr-namespace:ICSharpCode.WpfDesign.XamlDom.Tests;assembly=ICSharpCode.WpfDesign.XamlDom.Tests""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<ExampleClass OtherProp=""a"" />
<ExampleClass OtherProp=""b"" />
</ExampleClassContainer>
");
}
}
}

68
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/TestHelper.cs

@ -0,0 +1,68 @@ @@ -0,0 +1,68 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
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<T>(IEnumerable<T> e)
{
return new List<T>(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);
}
}
}
}

100
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/WhitespaceTests.cs

@ -0,0 +1,100 @@ @@ -0,0 +1,100 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using NUnit.Framework;
using System;
namespace ICSharpCode.WpfDesign.XamlDom.Tests
{
[TestFixture]
public class WhitespaceTests : TestHelper
{
[Test]
public void TrimSurroundingWhitespace()
{
TestLoading(@"
<t:ExampleClass
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:t=""clr-namespace:ICSharpCode.WpfDesign.XamlDom.Tests;assembly=ICSharpCode.WpfDesign.XamlDom.Tests""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
a test string
</t:ExampleClass>
");
}
[Test]
public void TrimConsecutiveWhitespace()
{
TestLoading(@"
<t:ExampleClass
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:t=""clr-namespace:ICSharpCode.WpfDesign.XamlDom.Tests;assembly=ICSharpCode.WpfDesign.XamlDom.Tests""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
a test string
</t:ExampleClass>
");
}
[Test]
public void ConvertLineFeedToSpace()
{
TestLoading(@"
<t:ExampleClass
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:t=""clr-namespace:ICSharpCode.WpfDesign.XamlDom.Tests;assembly=ICSharpCode.WpfDesign.XamlDom.Tests""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
a test
string
</t:ExampleClass>
");
}
[Test]
public void PreserveSurroundingWhitespace()
{
TestLoading(@"
<t:ExampleClass
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:t=""clr-namespace:ICSharpCode.WpfDesign.XamlDom.Tests;assembly=ICSharpCode.WpfDesign.XamlDom.Tests""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" xml:space=""preserve"">
a test string
</t:ExampleClass>
");
}
[Test]
public void PreserveConsecutiveWhitespace()
{
TestLoading(@"
<t:ExampleClass
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:t=""clr-namespace:ICSharpCode.WpfDesign.XamlDom.Tests;assembly=ICSharpCode.WpfDesign.XamlDom.Tests""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" xml:space=""preserve"">
a test string
</t:ExampleClass>
");
}
[Test]
public void PreserveLineFeed()
{
TestLoading(@"
<t:ExampleClass
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:t=""clr-namespace:ICSharpCode.WpfDesign.XamlDom.Tests;assembly=ICSharpCode.WpfDesign.XamlDom.Tests""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" xml:space=""preserve"">
a test
string
</t:ExampleClass>
");
}
}
}

63
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/WpfDesign.XamlDom.Tests.csproj

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{BD62F5BC-115F-4339-8B5B-96C7A21DC67E}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<OutputType>Library</OutputType>
<RootNamespace>ICSharpCode.WpfDesign.XamlDom.Tests</RootNamespace>
<AssemblyName>ICSharpCode.WpfDesign.XamlDom.Tests</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<OutputPath>bin\Debug\</OutputPath>
<DebugSymbols>True</DebugSymbols>
<DebugType>Full</DebugType>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<DefineConstants>DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>bin\Release\</OutputPath>
<DebugSymbols>False</DebugSymbols>
<DebugType>None</DebugType>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
<ItemGroup>
<Reference Include="nunit.framework">
<HintPath>..\..\..\..\..\Tools\NUnit\nunit.framework.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
<Private>True</Private>
</Reference>
<Reference Include="PresentationCore">
<Private>False</Private>
</Reference>
<Reference Include="PresentationFramework">
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase">
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\..\..\..\Main\GlobalAssemblyInfo.cs">
<Link>GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="ExampleClass.cs" />
<Compile Include="ExampleClassContainer.cs" />
<Compile Include="SamplesTests.cs" />
<Compile Include="SimpleLoadTests.cs" />
<Compile Include="TestHelper.cs" />
<Compile Include="WhitespaceTests.cs" />
<Compile Include="XamlTypeFinderTests.cs" />
<None Include="app.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Project\WpfDesign.XamlDom.csproj">
<Project>{88DA149F-21B2-48AB-82C4-28FB6BDFD783}</Project>
<Name>WpfDesign.XamlDom</Name>
</ProjectReference>
</ItemGroup>
</Project>

64
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/XamlTypeFinderTests.cs

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
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"));
}
}
}

15
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/app.config

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="NUnit">
<section name="TestRunner"
type="System.Configuration.NameValueSectionHandler" />
</sectionGroup>
</configSections>
<NUnit>
<TestRunner>
<!-- Valid values are STA,MTA. Others ignored. -->
<add key="ApartmentState" value="STA" />
</TestRunner>
</NUnit>
</configuration>

24
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.sln

@ -0,0 +1,24 @@ @@ -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
Loading…
Cancel
Save