Browse Source

XamlDom: support loading resources

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@3071 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 17 years ago
parent
commit
3fcf6c6f36
  1. 15
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/SamplesTests.cs
  2. 12
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs
  3. 62
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/MarkupExtensionParser.cs
  4. 1
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj
  5. 24
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlDocument.cs
  6. 18
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs
  7. 63
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs
  8. 91
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlPropertyInfo.cs
  9. 69
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTextValue.cs
  10. 102
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTypeResolverProvider.cs

15
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/SamplesTests.cs

@ -112,6 +112,21 @@ namespace ICSharpCode.WpfDesign.Tests.XamlDom
<Hyperlink NavigateUri=""Page2.xaml"">Go To Page 2</Hyperlink> <Hyperlink NavigateUri=""Page2.xaml"">Go To Page 2</Hyperlink>
</TextBlock> </TextBlock>
</StackPanel> </StackPanel>
</Page>");
}
[Test]
public void Resources()
{
TestLoading(@"<Page Name=""root""
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
>
<Page.Resources>
<SolidColorBrush x:Key=""MyBrush"" Color=""Gold""/>
</Page.Resources>
<StackPanel Background=""{StaticResource MyBrush}"">
</StackPanel>
</Page>"); </Page>");
} }
} }

12
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs

@ -21,9 +21,9 @@ namespace ICSharpCode.WpfDesign.XamlDom
public static bool IsCollectionType(Type type) public static bool IsCollectionType(Type type)
{ {
return typeof(IList).IsAssignableFrom(type) return typeof(IList).IsAssignableFrom(type)
|| typeof(IDictionary).IsAssignableFrom(type)
|| type.IsArray || type.IsArray
|| typeof(IAddChild).IsAssignableFrom(type); || typeof(IAddChild).IsAssignableFrom(type)
|| typeof(ResourceDictionary).IsAssignableFrom(type);
} }
public static void AddToCollection(Type collectionType, object collectionInstance, XamlPropertyValue newElement) public static void AddToCollection(Type collectionType, object collectionInstance, XamlPropertyValue newElement)
@ -35,6 +35,14 @@ namespace ICSharpCode.WpfDesign.XamlDom
} else { } else {
addChild.AddChild(newElement.GetValueFor(null)); addChild.AddChild(newElement.GetValueFor(null));
} }
} else if (collectionInstance is ResourceDictionary) {
object val = newElement.GetValueFor(null);
object key = newElement is XamlObject ? ((XamlObject)newElement).GetXamlAttribute("Key") : null;
if (key == null) {
if (val is Style)
key = ((Style)val).TargetType;
}
((ResourceDictionary)collectionInstance).Add(key, val);
} else { } else {
collectionType.InvokeMember( collectionType.InvokeMember(
"Add", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, "Add", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance,

62
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/MarkupExtensionParser.cs

@ -8,6 +8,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Runtime.Serialization; using System.Runtime.Serialization;
@ -218,10 +219,12 @@ namespace ICSharpCode.WpfDesign.XamlDom
static class MarkupExtensionParser static class MarkupExtensionParser
{ {
public static MarkupExtension ConstructMarkupExtension(string attributeText, XmlElement containingElement, XamlDocument document) public static MarkupExtension ConstructMarkupExtension(string attributeText, XamlObject containingObject, XamlTypeResolverProvider typeResolver)
{ {
if (containingElement == null) if (containingObject == null)
throw new ArgumentNullException("containingElement"); throw new ArgumentNullException("containingObject");
Debug.WriteLine("ConstructMarkupExtension " + attributeText);
List<MarkupExtensionToken> markupExtensionTokens = MarkupExtensionTokenizer.Tokenize(attributeText); List<MarkupExtensionToken> markupExtensionTokens = MarkupExtensionTokenizer.Tokenize(attributeText);
if (markupExtensionTokens.Count < 3 if (markupExtensionTokens.Count < 3
@ -233,26 +236,14 @@ namespace ICSharpCode.WpfDesign.XamlDom
} }
string typeName = markupExtensionTokens[1].Value; string typeName = markupExtensionTokens[1].Value;
string typeNamespaceUri; Type extensionType = typeResolver.Resolve(typeName + "Extension");
string typeLocalName;
if (typeName.Contains(":")) {
typeNamespaceUri = containingElement.GetNamespaceOfPrefix(typeName.Substring(0, typeName.IndexOf(':')));
typeLocalName = typeName.Substring(typeName.IndexOf(':') + 1);
} else {
typeNamespaceUri = containingElement.NamespaceURI;
typeLocalName = typeName;
}
if (string.IsNullOrEmpty(typeNamespaceUri))
throw new XamlMarkupExtensionParseException("Unrecognized namespace prefix in type " + typeName);
Type extensionType = null;
if (typeNamespaceUri == "http://schemas.microsoft.com/winfx/2006/xaml" && typeLocalName == "Type") {
extensionType = typeof(TypeExtension);
} else {
extensionType = document.TypeFinder.GetType(typeNamespaceUri, typeLocalName + "Extension");
}
if (extensionType == null || !typeof(MarkupExtension).IsAssignableFrom(extensionType)) { if (extensionType == null || !typeof(MarkupExtension).IsAssignableFrom(extensionType)) {
throw new XamlMarkupExtensionParseException("Unknown markup extension " + typeLocalName + "Extension in " + typeNamespaceUri); throw new XamlMarkupExtensionParseException("Unknown markup extension " + typeName + "Extension");
} }
if (extensionType == typeof(TypeExtension))
extensionType = typeof(MyTypeExtension);
if (extensionType == typeof(System.Windows.StaticResourceExtension))
extensionType = typeof(MyStaticResourceExtension);
List<string> positionalArgs = new List<string>(); List<string> positionalArgs = new List<string>();
List<KeyValuePair<string, string>> namedArgs = new List<KeyValuePair<string, string>>(); List<KeyValuePair<string, string>> namedArgs = new List<KeyValuePair<string, string>>();
@ -280,10 +271,11 @@ namespace ICSharpCode.WpfDesign.XamlDom
var ctorParameters = ctors[0].GetParameters(); var ctorParameters = ctors[0].GetParameters();
object[] ctorArguments = new object[positionalArgs.Count]; object[] ctorArguments = new object[positionalArgs.Count];
for (int i = 0; i < ctorArguments.Length; i++) { for (int i = 0; i < ctorArguments.Length; i++) {
TypeConverter c = TypeDescriptor.GetConverter(ctorParameters[i].ParameterType); Type parameterType = ctorParameters[i].ParameterType;
TypeConverter c = XamlNormalPropertyInfo.GetCustomTypeConverter(parameterType)
?? TypeDescriptor.GetConverter(parameterType);
ctorArguments[i] = XamlTextValue.AttributeTextToObject(positionalArgs[i], ctorArguments[i] = XamlTextValue.AttributeTextToObject(positionalArgs[i],
containingElement, containingObject,
document,
c); c);
} }
MarkupExtension result = (MarkupExtension)ctors[0].Invoke(ctorArguments); MarkupExtension result = (MarkupExtension)ctors[0].Invoke(ctorArguments);
@ -299,8 +291,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
throw new XamlMarkupExtensionParseException("Property not found: " + extensionType.FullName + "." + memberName); throw new XamlMarkupExtensionParseException("Property not found: " + extensionType.FullName + "." + memberName);
TypeConverter c = TypeDescriptor.GetConverter(property.PropertyType); TypeConverter c = TypeDescriptor.GetConverter(property.PropertyType);
object propValue = XamlTextValue.AttributeTextToObject(pair.Value, object propValue = XamlTextValue.AttributeTextToObject(pair.Value,
containingElement, containingObject,
document,
c); c);
property.SetValue(result, propValue, null); property.SetValue(result, propValue, null);
} }
@ -308,12 +299,25 @@ namespace ICSharpCode.WpfDesign.XamlDom
return result; return result;
} }
sealed class TypeExtension : System.Windows.Markup.TypeExtension sealed class MyTypeExtension : TypeExtension
{ {
public TypeExtension() {} public MyTypeExtension() {}
public MyTypeExtension(string typeName) : base(typeName) {}
}
sealed class MyStaticResourceExtension : System.Windows.StaticResourceExtension
{
public MyStaticResourceExtension() {}
public MyStaticResourceExtension(object resourceKey) : base(resourceKey) {}
public TypeExtension(string typeName) : base(typeName) public override object ProvideValue(IServiceProvider serviceProvider)
{ {
XamlTypeResolverProvider xamlTypeResolver = (XamlTypeResolverProvider)serviceProvider.GetService(typeof(XamlTypeResolverProvider));
if (xamlTypeResolver == null)
throw new XamlLoadException("XamlTypeResolverProvider not found.");
return xamlTypeResolver.FindResource(this.ResourceKey);
} }
} }
} }

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

@ -77,5 +77,6 @@
<Compile Include="XamlPropertyValue.cs" /> <Compile Include="XamlPropertyValue.cs" />
<Compile Include="XamlTextValue.cs" /> <Compile Include="XamlTextValue.cs" />
<Compile Include="XamlTypeFinder.cs" /> <Compile Include="XamlTypeFinder.cs" />
<Compile Include="XamlTypeResolverProvider.cs" />
</ItemGroup> </ItemGroup>
</Project> </Project>

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

@ -7,6 +7,7 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Windows.Markup;
using System.Xml; using System.Xml;
namespace ICSharpCode.WpfDesign.XamlDom namespace ICSharpCode.WpfDesign.XamlDom
@ -40,18 +41,29 @@ namespace ICSharpCode.WpfDesign.XamlDom
get { return _serviceProvider; } get { return _serviceProvider; }
} }
internal ITypeDescriptorContext GetTypeDescriptorContext() /// <summary>
/// Gets the type descriptor context used for type conversions.
/// </summary>
/// <param name="containingObject">The containing object, used when the
/// type descriptor context needs to resolve an XML namespace.</param>
internal ITypeDescriptorContext GetTypeDescriptorContext(XamlObject containingObject)
{ {
return new DummyTypeDescriptorContext(this); return new DummyTypeDescriptorContext(this, containingObject);
} }
sealed class DummyTypeDescriptorContext : ITypeDescriptorContext sealed class DummyTypeDescriptorContext : ITypeDescriptorContext
{ {
XamlDocument document; IServiceProvider baseServiceProvider;
public DummyTypeDescriptorContext(XamlDocument document) public DummyTypeDescriptorContext(XamlDocument document, XamlObject containingObject)
{ {
this.document = document; if (containingObject != null) {
if (containingObject.OwnerDocument != document)
throw new ArgumentException("Containing object must belong to the document!");
baseServiceProvider = new XamlTypeResolverProvider(containingObject);
} else {
baseServiceProvider = document.ServiceProvider;
}
} }
public IContainer Container { public IContainer Container {
@ -77,7 +89,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
public object GetService(Type serviceType) public object GetService(Type serviceType)
{ {
return document.ServiceProvider.GetService(serviceType); return baseServiceProvider.GetService(serviceType);
} }
} }

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

@ -59,6 +59,24 @@ namespace ICSharpCode.WpfDesign.XamlDom
} }
#endregion #endregion
XamlObject parentObject;
/// <summary>
/// Gets the parent object.
/// </summary>
public XamlObject ParentObject {
get {
return parentObject;
}
internal set { parentObject = value; }
}
internal override void OnParentPropertyChanged()
{
parentObject = (ParentProperty != null) ? ParentProperty.ParentObject : null;
base.OnParentPropertyChanged();
}
internal XmlElement XmlElement { internal XmlElement XmlElement {
get { return element; } get { return element; }
} }

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

@ -108,7 +108,12 @@ namespace ICSharpCode.WpfDesign.XamlDom
Type FindType(string namespaceUri, string localName) Type FindType(string namespaceUri, string localName)
{ {
Type elementType = settings.TypeFinder.GetType(namespaceUri, localName); return FindType(settings.TypeFinder, namespaceUri, localName);
}
static Type FindType(XamlTypeFinder typeFinder, string namespaceUri, string localName)
{
Type elementType = typeFinder.GetType(namespaceUri, localName);
if (elementType == null) if (elementType == null)
throw new XamlLoadException("Cannot find type " + localName + " in " + namespaceUri); throw new XamlLoadException("Cannot find type " + localName + " in " + namespaceUri);
return elementType; return elementType;
@ -124,12 +129,14 @@ namespace ICSharpCode.WpfDesign.XamlDom
readonly static object[] emptyObjectArray = new object[0]; readonly static object[] emptyObjectArray = new object[0];
XmlSpace currentXmlSpace = XmlSpace.None; XmlSpace currentXmlSpace = XmlSpace.None;
XamlObject currentXamlObject;
XamlObject ParseObject(XmlElement element) XamlObject ParseObject(XmlElement element)
{ {
Type elementType = FindType(element.NamespaceURI, element.LocalName); Type elementType = FindType(element.NamespaceURI, element.LocalName);
XmlSpace oldXmlSpace = currentXmlSpace; XmlSpace oldXmlSpace = currentXmlSpace;
XamlObject parentXamlObject = currentXamlObject;
if (element.HasAttribute("xml:space")) { if (element.HasAttribute("xml:space")) {
currentXmlSpace = (XmlSpace)Enum.Parse(typeof(XmlSpace), element.GetAttribute("xml:space"), true); currentXmlSpace = (XmlSpace)Enum.Parse(typeof(XmlSpace), element.GetAttribute("xml:space"), true);
} }
@ -160,7 +167,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
object instance; object instance;
if (initializeFromTextValueInsteadOfConstructor != null) { if (initializeFromTextValueInsteadOfConstructor != null) {
instance = TypeDescriptor.GetConverter(elementType).ConvertFromString( instance = TypeDescriptor.GetConverter(elementType).ConvertFromString(
document.GetTypeDescriptorContext(), document.GetTypeDescriptorContext(null),
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
initializeFromTextValueInsteadOfConstructor.Text); initializeFromTextValueInsteadOfConstructor.Text);
} else { } else {
@ -168,6 +175,8 @@ namespace ICSharpCode.WpfDesign.XamlDom
} }
XamlObject obj = new XamlObject(document, element, elementType, instance); XamlObject obj = new XamlObject(document, element, elementType, instance);
currentXamlObject = obj;
obj.ParentObject = parentXamlObject;
ISupportInitialize iSupportInitializeInstance = instance as ISupportInitialize; ISupportInitialize iSupportInitializeInstance = instance as ISupportInitialize;
if (iSupportInitializeInstance != null) { if (iSupportInitializeInstance != null) {
@ -185,12 +194,28 @@ namespace ICSharpCode.WpfDesign.XamlDom
ParseObjectAttribute(obj, attribute); ParseObjectAttribute(obj, attribute);
} }
if (!(obj.Instance is Style)) {
ParseObjectContent(obj, element, defaultProperty, initializeFromTextValueInsteadOfConstructor);
}
if (iSupportInitializeInstance != null) {
iSupportInitializeInstance.EndInit();
}
currentXmlSpace = oldXmlSpace;
currentXamlObject = parentXamlObject;
return obj;
}
void ParseObjectContent(XamlObject obj, XmlElement element, XamlPropertyInfo defaultProperty, XamlTextValue initializeFromTextValueInsteadOfConstructor)
{
XamlPropertyValue setDefaultValueTo = null; XamlPropertyValue setDefaultValueTo = null;
object defaultPropertyValue = null; object defaultPropertyValue = null;
XamlProperty defaultCollectionProperty = null; XamlProperty defaultCollectionProperty = null;
if (defaultProperty != null && defaultProperty.IsCollection && !element.IsEmpty) { if (defaultProperty != null && defaultProperty.IsCollection && !element.IsEmpty) {
defaultPropertyValue = defaultProperty.GetValue(instance); defaultPropertyValue = defaultProperty.GetValue(obj.Instance);
obj.AddProperty(defaultCollectionProperty = new XamlProperty(obj, defaultProperty)); obj.AddProperty(defaultCollectionProperty = new XamlProperty(obj, defaultProperty));
} }
@ -200,7 +225,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
// here, but let's try to imitate it as good as possible // here, but let's try to imitate it as good as possible
if (defaultProperty != null && !defaultProperty.IsCollection) { if (defaultProperty != null && !defaultProperty.IsCollection) {
for (; combinedNormalizedChildNodes > 0; combinedNormalizedChildNodes--) { for (; combinedNormalizedChildNodes > 0; combinedNormalizedChildNodes--) {
defaultProperty.GetValue(instance); defaultProperty.GetValue(obj.Instance);
} }
} }
@ -213,7 +238,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
// I don't know why the official XamlReader runs the property getter // I don't know why the official XamlReader runs the property getter
// here, but let's try to imitate it as good as possible // here, but let's try to imitate it as good as possible
if (defaultProperty != null && !defaultProperty.IsCollection) { if (defaultProperty != null && !defaultProperty.IsCollection) {
defaultProperty.GetValue(instance); defaultProperty.GetValue(obj.Instance);
} }
ParseObjectChildElementAsPropertyElement(obj, childElement, defaultProperty, defaultPropertyValue); ParseObjectChildElementAsPropertyElement(obj, childElement, defaultProperty, defaultPropertyValue);
continue; continue;
@ -224,8 +249,8 @@ namespace ICSharpCode.WpfDesign.XamlDom
XamlPropertyValue childValue = ParseValue(childNode); XamlPropertyValue childValue = ParseValue(childNode);
if (childValue != null) { if (childValue != null) {
if (defaultProperty != null && defaultProperty.IsCollection) { if (defaultProperty != null && defaultProperty.IsCollection) {
CollectionSupport.AddToCollection(defaultProperty.ReturnType, defaultPropertyValue, childValue);
defaultCollectionProperty.ParserAddCollectionElement(null, childValue); defaultCollectionProperty.ParserAddCollectionElement(null, childValue);
CollectionSupport.AddToCollection(defaultProperty.ReturnType, defaultPropertyValue, childValue);
} else { } else {
if (setDefaultValueTo != null) if (setDefaultValueTo != null)
throw new XamlLoadException("default property may have only one value assigned"); throw new XamlLoadException("default property may have only one value assigned");
@ -238,23 +263,15 @@ namespace ICSharpCode.WpfDesign.XamlDom
{ {
// Runs even when defaultValueSet==false! // Runs even when defaultValueSet==false!
// Again, no idea why the official XamlReader does this. // Again, no idea why the official XamlReader does this.
defaultProperty.GetValue(instance); defaultProperty.GetValue(obj.Instance);
} }
if (setDefaultValueTo != null) { if (setDefaultValueTo != null) {
if (defaultProperty == null) { if (defaultProperty == null) {
throw new XamlLoadException("This element does not have a default value, cannot assign to it"); throw new XamlLoadException("This element does not have a default value, cannot assign to it");
} }
defaultProperty.SetValue(instance, setDefaultValueTo.GetValueFor(defaultProperty));
obj.AddProperty(new XamlProperty(obj, defaultProperty, setDefaultValueTo)); obj.AddProperty(new XamlProperty(obj, defaultProperty, setDefaultValueTo));
defaultProperty.SetValue(obj.Instance, setDefaultValueTo.GetValueFor(defaultProperty));
} }
if (iSupportInitializeInstance != null) {
iSupportInitializeInstance.EndInit();
}
currentXmlSpace = oldXmlSpace;
return obj;
} }
int combinedNormalizedChildNodes; int combinedNormalizedChildNodes;
@ -319,7 +336,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
return null; return null;
} }
static XamlPropertyInfo FindProperty(object elementInstance, Type propertyType, string propertyName) internal static XamlPropertyInfo FindProperty(object elementInstance, Type propertyType, string propertyName)
{ {
PropertyDescriptorCollection properties; PropertyDescriptorCollection properties;
if (elementInstance != null) { if (elementInstance != null) {
@ -375,17 +392,17 @@ namespace ICSharpCode.WpfDesign.XamlDom
XamlPropertyInfo GetPropertyInfo(object elementInstance, Type elementType, XmlAttribute attribute) XamlPropertyInfo GetPropertyInfo(object elementInstance, Type elementType, XmlAttribute attribute)
{ {
if (attribute.LocalName.Contains(".")) { if (attribute.LocalName.Contains(".")) {
return GetPropertyInfo(elementInstance, elementType, GetAttributeNamespace(attribute), attribute.LocalName); return GetPropertyInfo(settings.TypeFinder, elementInstance, elementType, GetAttributeNamespace(attribute), attribute.LocalName);
} else { } else {
return FindProperty(elementInstance, elementType, attribute.LocalName); return FindProperty(elementInstance, elementType, attribute.LocalName);
} }
} }
XamlPropertyInfo GetPropertyInfo(object elementInstance, Type elementType, string xmlNamespace, string localName) internal static XamlPropertyInfo GetPropertyInfo(XamlTypeFinder typeFinder, object elementInstance, Type elementType, string xmlNamespace, string localName)
{ {
string typeName, propertyName; string typeName, propertyName;
SplitQualifiedIdentifier(localName, out typeName, out propertyName); SplitQualifiedIdentifier(localName, out typeName, out propertyName);
Type propertyType = FindType(xmlNamespace, typeName); Type propertyType = FindType(typeFinder, xmlNamespace, typeName);
if (elementType == propertyType || propertyType.IsAssignableFrom(elementType)) { if (elementType == propertyType || propertyType.IsAssignableFrom(elementType)) {
return FindProperty(elementInstance, propertyType, propertyName); return FindProperty(elementInstance, propertyType, propertyName);
} else { } else {
@ -406,8 +423,8 @@ namespace ICSharpCode.WpfDesign.XamlDom
{ {
XamlPropertyInfo propertyInfo = GetPropertyInfo(obj.Instance, obj.ElementType, attribute); XamlPropertyInfo propertyInfo = GetPropertyInfo(obj.Instance, obj.ElementType, attribute);
XamlTextValue textValue = new XamlTextValue(document, attribute); XamlTextValue textValue = new XamlTextValue(document, attribute);
propertyInfo.SetValue(obj.Instance, textValue.GetValueFor(propertyInfo));
obj.AddProperty(new XamlProperty(obj, propertyInfo, textValue)); obj.AddProperty(new XamlProperty(obj, propertyInfo, textValue));
propertyInfo.SetValue(obj.Instance, textValue.GetValueFor(propertyInfo));
} }
static bool ObjectChildElementIsPropertyElement(XmlElement element) static bool ObjectChildElementIsPropertyElement(XmlElement element)
@ -420,7 +437,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
Debug.Assert(element.LocalName.Contains(".")); Debug.Assert(element.LocalName.Contains("."));
// this is a element property syntax // this is a element property syntax
XamlPropertyInfo propertyInfo = GetPropertyInfo(obj.Instance, obj.ElementType, element.NamespaceURI, element.LocalName); XamlPropertyInfo propertyInfo = GetPropertyInfo(settings.TypeFinder, obj.Instance, obj.ElementType, element.NamespaceURI, element.LocalName);
bool valueWasSet = false; bool valueWasSet = false;
object collectionInstance = null; object collectionInstance = null;
@ -458,10 +475,10 @@ namespace ICSharpCode.WpfDesign.XamlDom
if (valueWasSet) if (valueWasSet)
throw new XamlLoadException("non-collection property may have only one child element"); throw new XamlLoadException("non-collection property may have only one child element");
valueWasSet = true; valueWasSet = true;
propertyInfo.SetValue(obj.Instance, childValue.GetValueFor(propertyInfo));
XamlProperty xp = new XamlProperty(obj, propertyInfo, childValue); XamlProperty xp = new XamlProperty(obj, propertyInfo, childValue);
xp.ParserSetPropertyElement(element); xp.ParserSetPropertyElement(element);
obj.AddProperty(xp); obj.AddProperty(xp);
propertyInfo.SetValue(obj.Instance, childValue.GetValueFor(propertyInfo));
} }
} }
} }

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

@ -42,6 +42,10 @@ namespace ICSharpCode.WpfDesign.XamlDom
readonly DependencyProperty property; readonly DependencyProperty property;
readonly bool isAttached; readonly bool isAttached;
public DependencyProperty Property {
get { return property; }
}
public XamlDependencyPropertyInfo(DependencyProperty property, bool isAttached) public XamlDependencyPropertyInfo(DependencyProperty property, bool isAttached)
{ {
Debug.Assert(property != null); Debug.Assert(property != null);
@ -101,7 +105,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
} }
} }
#endregion #endregion
#region XamlNormalPropertyInfo #region XamlNormalPropertyInfo
internal sealed class XamlNormalPropertyInfo : XamlPropertyInfo internal sealed class XamlNormalPropertyInfo : XamlPropertyInfo
{ {
@ -141,10 +145,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
public override TypeConverter TypeConverter { public override TypeConverter TypeConverter {
get { get {
if (_propertyDescriptor.PropertyType == typeof(object)) return GetCustomTypeConverter(_propertyDescriptor.PropertyType) ?? _propertyDescriptor.Converter;
return null;
else
return _propertyDescriptor.Converter;
} }
} }
@ -167,6 +168,84 @@ namespace ICSharpCode.WpfDesign.XamlDom
return CollectionSupport.IsCollectionType(_propertyDescriptor.PropertyType); return CollectionSupport.IsCollectionType(_propertyDescriptor.PropertyType);
} }
} }
public static readonly TypeConverter StringTypeConverter = TypeDescriptor.GetConverter(typeof(string));
public static TypeConverter GetCustomTypeConverter(Type propertyType)
{
if (propertyType == typeof(object))
return StringTypeConverter;
else if (propertyType == typeof(Type))
return TypeTypeConverter.Instance;
else if (propertyType == typeof(DependencyProperty))
return DependencyPropertyConverter.Instance;
else
return null;
}
sealed class TypeTypeConverter : TypeConverter
{
public readonly static TypeTypeConverter Instance = new TypeTypeConverter();
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;
else
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value == null)
return null;
if (value is string) {
IXamlTypeResolver xamlTypeResolver = (IXamlTypeResolver)context.GetService(typeof(IXamlTypeResolver));
if (xamlTypeResolver == null)
throw new XamlLoadException("IXamlTypeResolver not found in type descriptor context.");
return xamlTypeResolver.Resolve((string)value);
} else {
return base.ConvertFrom(context, culture, value);
}
}
}
sealed class DependencyPropertyConverter : TypeConverter
{
public readonly static DependencyPropertyConverter Instance = new DependencyPropertyConverter();
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;
else
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value == null)
return null;
if (value is string) {
XamlTypeResolverProvider xamlTypeResolver = (XamlTypeResolverProvider)context.GetService(typeof(XamlTypeResolverProvider));
if (xamlTypeResolver == null)
throw new XamlLoadException("XamlTypeResolverProvider not found in type descriptor context.");
XamlPropertyInfo prop = xamlTypeResolver.ResolveProperty((string)value);
if (prop == null)
throw new XamlLoadException("Could not find property " + value + ".");
XamlDependencyPropertyInfo depProp = prop as XamlDependencyPropertyInfo;
if (depProp != null)
return depProp.Property;
FieldInfo field = prop.TargetType.GetField(prop.Name + "Property", BindingFlags.Public | BindingFlags.Static);
if (field != null && field.FieldType == typeof(DependencyProperty)) {
return (DependencyProperty)field.GetValue(null);
}
throw new XamlLoadException("Property " + value + " is not a dependency property.");
} else {
return base.ConvertFrom(context, culture, value);
}
}
}
} }
#endregion #endregion
@ -208,7 +287,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
} }
public override TypeConverter TypeConverter { public override TypeConverter TypeConverter {
get { return null; } get { return XamlNormalPropertyInfo.StringTypeConverter; }
} }
public override string FullyQualifiedName { public override string FullyQualifiedName {

69
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTextValue.cs

@ -109,83 +109,40 @@ namespace ICSharpCode.WpfDesign.XamlDom
return b.ToString(); return b.ToString();
} }
static readonly TypeConverter stringTypeConverter = TypeDescriptor.GetConverter(typeof(string));
internal override object GetValueFor(XamlPropertyInfo targetProperty) internal override object GetValueFor(XamlPropertyInfo targetProperty)
{ {
if (ParentProperty == null)
throw new InvalidOperationException("Cannot call GetValueFor while ParentProperty is null");
if (attribute != null) { if (attribute != null) {
return AttributeTextToObject(attribute.Value, attribute.OwnerElement, document, return AttributeTextToObject(attribute.Value, ParentProperty.ParentObject,
targetProperty != null ? targetProperty.TypeConverter : stringTypeConverter); targetProperty != null ? targetProperty.TypeConverter : XamlNormalPropertyInfo.StringTypeConverter);
} }
if (targetProperty == null) if (targetProperty == null)
return this.Text; return this.Text;
TypeConverter converter = targetProperty.TypeConverter; return targetProperty.TypeConverter.ConvertFromString(
if (converter != null) { document.GetTypeDescriptorContext(ParentProperty.ParentObject),
return converter.ConvertFromString(document.GetTypeDescriptorContext(), CultureInfo.InvariantCulture, this.Text); CultureInfo.InvariantCulture, this.Text);
} else {
return this.Text;
}
} }
internal static object AttributeTextToObject(string attributeText, XmlElement containingElement, internal static object AttributeTextToObject(string attributeText, XamlObject containingObject,
XamlDocument document, TypeConverter typeConverter) TypeConverter typeConverter)
{ {
if (typeConverter == null)
typeConverter = stringTypeConverter;
if (attributeText.StartsWith("{}")) { if (attributeText.StartsWith("{}")) {
return typeConverter.ConvertFromString( return typeConverter.ConvertFromString(
document.GetTypeDescriptorContext(), CultureInfo.InvariantCulture, containingObject.OwnerDocument.GetTypeDescriptorContext(containingObject), CultureInfo.InvariantCulture,
attributeText.Substring(2)); attributeText.Substring(2));
} else if (attributeText.StartsWith("{")) { } else if (attributeText.StartsWith("{")) {
XamlTypeResolverProvider xtrp = new XamlTypeResolverProvider(document, containingElement, document.ServiceProvider); XamlTypeResolverProvider xtrp = new XamlTypeResolverProvider(containingObject);
MarkupExtension extension = MarkupExtensionParser.ConstructMarkupExtension( MarkupExtension extension = MarkupExtensionParser.ConstructMarkupExtension(
attributeText, containingElement, document); attributeText, containingObject, xtrp);
return extension.ProvideValue(xtrp); return extension.ProvideValue(xtrp);
} else { } else {
return typeConverter.ConvertFromString( return typeConverter.ConvertFromString(
document.GetTypeDescriptorContext(), CultureInfo.InvariantCulture, containingObject.OwnerDocument.GetTypeDescriptorContext(containingObject), CultureInfo.InvariantCulture,
attributeText); attributeText);
} }
} }
sealed class XamlTypeResolverProvider : IXamlTypeResolver, IServiceProvider
{
XamlDocument document;
XmlElement containingElement;
IServiceProvider baseProvider;
public XamlTypeResolverProvider(XamlDocument document, XmlElement containingElement, IServiceProvider baseProvider)
{
this.document = document;
this.containingElement = containingElement;
this.baseProvider = baseProvider;
}
public Type Resolve(string typeName)
{
string typeNamespaceUri;
string typeLocalName;
if (typeName.Contains(":")) {
typeNamespaceUri = containingElement.GetNamespaceOfPrefix(typeName.Substring(0, typeName.IndexOf(':')));
typeLocalName = typeName.Substring(typeName.IndexOf(':') + 1);
} else {
typeNamespaceUri = containingElement.NamespaceURI;
typeLocalName = typeName;
}
if (string.IsNullOrEmpty(typeNamespaceUri))
throw new XamlMarkupExtensionParseException("Unrecognized namespace prefix in type " + typeName);
return document.TypeFinder.GetType(typeNamespaceUri, typeLocalName);
}
public object GetService(Type serviceType)
{
if (serviceType == typeof(IXamlTypeResolver))
return this;
else
return baseProvider.GetService(serviceType);
}
}
internal override void RemoveNodeFromParent() internal override void RemoveNodeFromParent()
{ {
if (attribute != null) if (attribute != null)

102
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTypeResolverProvider.cs

@ -0,0 +1,102 @@
// <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.Diagnostics;
using System.Globalization;
using System.Text;
using System.Windows;
using System.Windows.Markup;
using System.Xml;
namespace ICSharpCode.WpfDesign.XamlDom
{
sealed class XamlTypeResolverProvider : IXamlTypeResolver, IServiceProvider
{
XamlDocument document;
XamlObject containingObject;
XmlElement containingElement;
public XamlTypeResolverProvider(XamlObject containingObject)
{
if (containingObject == null)
throw new ArgumentNullException("containingObject");
this.document = containingObject.OwnerDocument;
this.containingObject = containingObject;
this.containingElement = containingObject.XmlElement;
}
public Type Resolve(string typeName)
{
string typeNamespaceUri;
string typeLocalName;
if (typeName.Contains(":")) {
typeNamespaceUri = containingElement.GetNamespaceOfPrefix(typeName.Substring(0, typeName.IndexOf(':')));
typeLocalName = typeName.Substring(typeName.IndexOf(':') + 1);
} else {
typeNamespaceUri = containingElement.NamespaceURI;
typeLocalName = typeName;
}
if (string.IsNullOrEmpty(typeNamespaceUri))
throw new XamlMarkupExtensionParseException("Unrecognized namespace prefix in type " + typeName);
return document.TypeFinder.GetType(typeNamespaceUri, typeLocalName);
}
public object GetService(Type serviceType)
{
if (serviceType == typeof(IXamlTypeResolver) || serviceType == typeof(XamlTypeResolverProvider))
return this;
else
return document.ServiceProvider.GetService(serviceType);
}
public XamlPropertyInfo ResolveProperty(string propertyName)
{
string propertyNamespace;
if (propertyName.Contains(":")) {
propertyNamespace = containingElement.GetNamespaceOfPrefix(propertyName.Substring(0, propertyName.IndexOf(':')));
propertyName = propertyName.Substring(propertyName.IndexOf(':') + 1);
} else {
propertyNamespace = containingElement.NamespaceURI;
}
Type elementType = null;
XamlObject obj = containingObject;
while (obj != null) {
Style style = obj.Instance as Style;
if (style != null && style.TargetType != null) {
elementType = style.TargetType;
break;
}
obj = obj.ParentObject;
}
if (propertyName.Contains(".")) {
return XamlParser.GetPropertyInfo(document.TypeFinder, null, elementType, propertyNamespace, propertyName);
} else if (elementType != null) {
return XamlParser.FindProperty(null, elementType, propertyName);
} else {
return null;
}
}
public object FindResource(object key)
{
XamlObject obj = containingObject;
while (obj != null) {
FrameworkElement el = obj.Instance as FrameworkElement;
if (el != null) {
object val = el.Resources[key];
if (val != null)
return val;
}
obj = obj.ParentObject;
}
return null;
}
}
}
Loading…
Cancel
Save