Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2218 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
21 changed files with 1843 additions and 0 deletions
@ -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)] |
@ -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> |
@ -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"; |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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) |
||||||
|
{ |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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
|
||||||
|
} |
||||||
|
} |
@ -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
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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("")] |
@ -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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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>");
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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> |
||||||
|
");
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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> |
||||||
|
");
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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> |
@ -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")); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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> |
@ -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…
Reference in new issue