Browse Source

template binding and xaml extensions operational

pull/916/head
donandren 9 years ago
committed by Andrey Kunchev
parent
commit
d55a2b2227
  1. 11
      src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoaderPortableXaml.cs
  2. 55
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs
  3. 35
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/RelativeSourceExtension.cs
  4. 2
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/Standard/StaticExtension.cs
  5. 2
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/Standard/TypeExtension.cs
  6. 16
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticExtension.cs
  7. 29
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StyleResourceExtension.cs
  8. 50
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/TemplateBindingExtension.cs
  9. 24
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/TypeExtension.cs
  10. 47
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlSchemaContext.cs
  11. 83
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlType.cs

11
src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoaderPortableXaml.cs

@ -195,13 +195,18 @@ namespace Avalonia.Markup.Xaml
}
}
internal static object LoadFromReader(XamlReader reader, object instance = null)
internal static object LoadFromReader(XamlReader reader, object instance)
{
var writer = AvaloniaXamlObjectWriter.Create(_context, instance);
XamlServices.Transform(reader, writer);
XamlServices.Transform(reader, writer);
return writer.Result;
return writer.Result;
}
internal static object LoadFromReader(XamlReader reader)
{
return XamlServices.Load(reader);
}
/// <summary>

55
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs

@ -1,12 +1,64 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using OmniXaml;
using Avalonia.Data;
using Avalonia.Markup.Xaml.Data;
using System;
namespace Avalonia.Markup.Xaml.MarkupExtensions
{
#if !OMNIXAML
using Portable.Xaml.Markup;
[MarkupExtensionReturnType(typeof(Binding))]
public class BindingExtension : MarkupExtension
{
public BindingExtension()
{
}
public BindingExtension(string path)
{
Path = path;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return new Binding
{
Converter = Converter,
ConverterParameter = ConverterParameter,
ElementName = ElementName,
FallbackValue = FallbackValue,
Mode = Mode,
Path = Path,
Priority = Priority,
};
}
public IValueConverter Converter { get; set; }
public object ConverterParameter { get; set; }
public string ElementName { get; set; }
public object FallbackValue { get; set; } = AvaloniaProperty.UnsetValue;
public BindingMode Mode { get; set; }
[ConstructorArgument("path")]
public string Path { get; set; }
public BindingPriority Priority { get; set; } = BindingPriority.LocalValue;
public object Source { get; set; }
}
#else
using OmniXaml;
public class BindingExtension : MarkupExtension
{
public BindingExtension()
@ -41,4 +93,5 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
public BindingPriority Priority { get; set; } = BindingPriority.LocalValue;
public object Source { get; set; }
}
#endif
}

35
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/RelativeSourceExtension.cs

@ -1,11 +1,43 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using OmniXaml;
using Avalonia.Markup.Xaml.Data;
namespace Avalonia.Markup.Xaml.MarkupExtensions
{
#if !OMNIXAML
using System;
using Portable.Xaml.Markup;
public class RelativeSourceExtension : MarkupExtension
{
public RelativeSourceExtension()
{
}
public RelativeSourceExtension(RelativeSourceMode mode)
{
Mode = mode;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return new RelativeSource
{
Mode = Mode,
};
}
[ConstructorArgument("mode")]
public RelativeSourceMode Mode { get; set; }
}
#else
using OmniXaml;
public class RelativeSourceExtension : MarkupExtension
{
public RelativeSourceExtension()
@ -27,4 +59,5 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
public RelativeSourceMode Mode { get; set; }
}
#endif
}

2
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/Standard/StaticExtension.cs

@ -9,6 +9,7 @@ using Glass.Core;
namespace Avalonia.Markup.Xaml.MarkupExtensions.Standard
{
#if OMNIXAML
public class StaticExtension : MarkupExtension
{
public StaticExtension()
@ -83,4 +84,5 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.Standard
throw new ArgumentException($"Static member '{type}.{name}' not found.");
}
}
#endif
}

2
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/Standard/TypeExtension.cs

@ -9,6 +9,7 @@ using Glass.Core;
namespace Avalonia.Markup.Xaml.MarkupExtensions.Standard
{
#if OMNIXAML
[ContentProperty("TargetType")]
public class TypeExtension : MarkupExtension
{
@ -46,4 +47,5 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.Standard
return ResolveFromString(TypeName, markupExtensionContext.ValueContext.TypeRepository);
}
}
#endif
}

16
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticExtension.cs

@ -4,11 +4,22 @@
using System;
using System.Linq;
using System.Reflection;
using OmniXaml;
using Glass.Core;
namespace Avalonia.Markup.Xaml.MarkupExtensions
{
#if !OMNIXAML
//TODO: check do we need something more than std Portable.xaml static??
public class StaticExtension : Portable.Xaml.Markup.StaticExtension
{
}
#else
using OmniXaml;
using Glass.Core;
public class StaticExtension : MarkupExtension
{
public StaticExtension()
@ -83,4 +94,5 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
throw new ArgumentException($"Static member '{type}.{name}' not found.");
}
}
#endif
}

29
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StyleResourceExtension.cs

@ -3,13 +3,39 @@
using System;
using System.Reactive.Linq;
using OmniXaml;
using Avalonia.LogicalTree;
using Avalonia.Markup.Xaml.Data;
using Avalonia.Styling;
namespace Avalonia.Markup.Xaml.MarkupExtensions
{
#if !OMNIXAML
using Portable.Xaml.Markup;
[MarkupExtensionReturnType(typeof(StyleResourceBinding))]
public class StyleResourceExtension : MarkupExtension
{
public StyleResourceExtension(string name)
{
Name = name;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return new StyleResourceBinding(this.Name);
}
[ConstructorArgument("name")]
public string Name { get; set; }
}
#else
using OmniXaml;
public class StyleResourceExtension : MarkupExtension
{
public StyleResourceExtension(string name)
@ -24,4 +50,5 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
public string Name { get; set; }
}
#endif
}

50
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/TemplateBindingExtension.cs

@ -1,12 +1,59 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using OmniXaml;
using Avalonia.Data;
using Avalonia.Markup.Xaml.Data;
namespace Avalonia.Markup.Xaml.MarkupExtensions
{
#if !OMNIXAML
using System;
using Portable.Xaml.Markup;
[MarkupExtensionReturnType(typeof(Binding))]
public class TemplateBindingExtension : MarkupExtension
{
public TemplateBindingExtension()
{
}
public TemplateBindingExtension(string path)
{
Path = path;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return new Binding
{
Converter = Converter,
ElementName = ElementName,
Mode = Mode,
RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent),
Path = Path,
Priority = Priority,
};
}
public IValueConverter Converter { get; set; }
public string ElementName { get; set; }
public object FallbackValue { get; set; }
public BindingMode Mode { get; set; }
[ConstructorArgument("path")]
public string Path { get; set; }
public BindingPriority Priority { get; set; } = BindingPriority.TemplatedParent;
}
#else
using OmniXaml;
public class TemplateBindingExtension : MarkupExtension
{
public TemplateBindingExtension()
@ -38,4 +85,5 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
public string Path { get; set; }
public BindingPriority Priority { get; set; } = BindingPriority.TemplatedParent;
}
#endif
}

24
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/TypeExtension.cs

@ -1,14 +1,24 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using OmniXaml;
using OmniXaml.Attributes;
using OmniXaml.Typing;
using Glass.Core;
namespace Avalonia.Markup.Xaml.MarkupExtensions
{
#if !OMNIXAML
//TODO: check do we need something more than std Portable.xaml type??
public class TypeExtension : Portable.Xaml.Markup.TypeExtension
{
}
#else
using System;
using OmniXaml;
using OmniXaml.Attributes;
using OmniXaml.Typing;
using Glass.Core;
[ContentProperty("TargetType")]
public class TypeExtension : MarkupExtension
{
@ -46,4 +56,6 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
return ResolveFromString(TypeName, markupExtensionContext.ValueContext.TypeRepository);
}
}
#endif
}

47
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlSchemaContext.cs

@ -5,6 +5,8 @@ using System.Reflection;
using Avalonia.Markup.Xaml.Context;
using Portable.Xaml;
using Portable.Xaml.ComponentModel;
using am = Avalonia.Metadata;
using Avalonia.Data;
namespace Avalonia.Markup.Xaml.PortableXaml
{
@ -51,10 +53,15 @@ namespace Avalonia.Markup.Xaml.PortableXaml
}
}
Type type = _avaloniaTypeProvider.FindType(xmlNamespace, xmlLocalName, genArgs);
// MarkupExtension type could omit "Extension" part in XML name.
Type type = _avaloniaTypeProvider.FindType(xmlNamespace, xmlLocalName, genArgs)
?? _avaloniaTypeProvider.FindType(xmlNamespace,
xmlLocalName + "Extension",
genArgs);
if (type == null)
{
//let's try the simple types
//in Portable xaml xmlns:sys='clr-namespace:System;assembly=mscorlib'
//and sys:Double is not resolved
@ -118,12 +125,44 @@ namespace Avalonia.Markup.Xaml.PortableXaml
public override XamlType GetXamlType(Type type)
{
if (type.FullName.StartsWith("Avalonia."))
//if (type.FullName.StartsWith("Avalonia."))
//{
// return new AvaloniaXamlType(type, this);
//}
return base.GetXamlType(type);
}
protected override XamlMember GetAttachableProperty(string attachablePropertyName, MethodInfo getter, MethodInfo setter)
{
return base.GetAttachableProperty(attachablePropertyName, getter, setter);
}
protected override XamlMember GetProperty(PropertyInfo pi)
{
Type objType = pi.DeclaringType;
string name = pi.Name;
var avProp = AvaloniaPropertyRegistry.Instance.FindRegistered(objType, name);
var assignBindingAttr = pi.GetCustomAttribute<AssignBindingAttribute>();
if (avProp != null)
{
return new AvaloniaXamlType(type, this);
return new AvaloniaPropertyXamlMember(avProp, pi, this)
{
AssignBinding = assignBindingAttr != null
};
}
return base.GetXamlType(type);
var dependAttr = pi.GetCustomAttribute<am.DependsOnAttribute>();
if (dependAttr != null)
{
return new DependOnXamlMember(dependAttr.Name, pi, this);
}
return base.GetProperty(pi);
}
}
}

83
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlType.cs

@ -1,31 +1,94 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Avalonia.Data;
using Portable.Xaml;
using Portable.Xaml.Schema;
using am = Avalonia.Metadata;
namespace Avalonia.Markup.Xaml.PortableXaml
{
public class AvaloniaXamlType : XamlType
//public class AvaloniaXamlType : XamlType
//{
// public AvaloniaXamlType(Type underlyingType, XamlSchemaContext schemaContext) :
// base(underlyingType, schemaContext)
// {
// }
// protected override XamlMember LookupMember(string name, bool skipReadOnlyCheck)
// {
// return base.LookupMember(name, skipReadOnlyCheck);
// }
//}
public class AvaloniaPropertyXamlMember : XamlMember
{
public AvaloniaXamlType(Type underlyingType, XamlSchemaContext schemaContext) :
base(underlyingType, schemaContext)
public bool AssignBinding { get; set; } = false;
public AvaloniaProperty Property { get; }
public AvaloniaPropertyXamlMember(AvaloniaProperty property,
PropertyInfo propertyInfo,
XamlSchemaContext schemaContext) :
base(propertyInfo, schemaContext)
{
Property = property;
}
protected override XamlMember LookupMember(string name, bool skipReadOnlyCheck)
protected override XamlMemberInvoker LookupInvoker()
{
var pi = UnderlyingType.GetRuntimeProperty(name);
return new AvaloniaPropertyInvoker(this);
}
var dependAttr = pi.GetCustomAttribute<am.DependsOnAttribute>();
private class AvaloniaPropertyInvoker : XamlMemberInvoker
{
public AvaloniaPropertyInvoker(XamlMember member) : base(member)
{
}
if (dependAttr != null)
public override void SetValue(object instance, object value)
{
return new DependOnXamlMember(dependAttr.Name, pi, SchemaContext);
if (Property != null)
{
var obj = ((IAvaloniaObject)instance);
if (value is IBinding && !Member.AssignBinding)
{
ApplyBinding(obj, (IBinding)value);
}
else
{
obj.SetValue(Property, value);
}
}
else
{
base.SetValue(instance, value);
}
}
public override object GetValue(object instance)
{
if (Property != null)
{
return ((IAvaloniaObject)instance).GetValue(Property);
}
else
{
return base.GetValue(instance);
}
}
return base.LookupMember(name, skipReadOnlyCheck);
private void ApplyBinding(IAvaloniaObject obj, IBinding binding)
{
//TODO: in Context.PropertyAccessor there is
//some quirk stuff check it later
obj.Bind(Property, binding);
}
private AvaloniaProperty Property => Member.Property;
private new AvaloniaPropertyXamlMember Member =>
(AvaloniaPropertyXamlMember)base.Member;
}
}

Loading…
Cancel
Save