|
|
@@ -1,10 +1,14 @@
|
|
|
-using System;
|
|
|
-using System.Collections.Generic;
|
|
|
-using System.Reflection;
|
|
|
+using Avalonia.Controls;
|
|
|
using Avalonia.Data;
|
|
|
+using Avalonia.Markup.Xaml.Data;
|
|
|
+using Avalonia.Markup.Xaml.MarkupExtensions;
|
|
|
using Portable.Xaml;
|
|
|
-using Portable.Xaml.Markup;
|
|
|
+using Portable.Xaml.ComponentModel;
|
|
|
using Portable.Xaml.Schema;
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Reflection;
|
|
|
+using System.Xml.Serialization;
|
|
|
|
|
|
namespace Avalonia.Markup.Xaml.PortableXaml
|
|
|
{
|
|
|
@@ -18,23 +22,95 @@ namespace Avalonia.Markup.Xaml.PortableXaml
|
|
|
|
|
|
public class BindingXamlType : AvaloniaXamlType
|
|
|
{
|
|
|
- public BindingXamlType(Type underlyingType, XamlSchemaContext schemaContext) :
|
|
|
+ public static BindingXamlType Create(Type type, XamlSchemaContext schemaContext)
|
|
|
+ {
|
|
|
+ if (type == typeof(Binding))
|
|
|
+ {
|
|
|
+ //in xmal we need to use the extension
|
|
|
+ type = typeof(BindingExtension);
|
|
|
+ }
|
|
|
+
|
|
|
+ return new BindingXamlType(type, schemaContext);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static HashSet<Type> _notAssignable =
|
|
|
+ new HashSet<Type>()
|
|
|
+ {
|
|
|
+ typeof (IXmlSerializable)
|
|
|
+ };
|
|
|
+
|
|
|
+ private BindingXamlType(Type underlyingType, XamlSchemaContext schemaContext) :
|
|
|
base(underlyingType, schemaContext)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
public override bool CanAssignTo(XamlType xamlType)
|
|
|
{
|
|
|
+ if (_notAssignable.Contains(xamlType.UnderlyingType))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
return true;
|
|
|
}
|
|
|
+
|
|
|
+ protected override XamlMember LookupAliasedProperty(XamlDirective directive)
|
|
|
+ {
|
|
|
+ return base.LookupAliasedProperty(directive);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override bool LookupIsMarkupExtension()
|
|
|
+ {
|
|
|
+ return base.LookupIsMarkupExtension();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- public class AvaloniaPropertyXamlMember : XamlMember
|
|
|
+ public class PropertyXamlMember : XamlMember
|
|
|
+ {
|
|
|
+ protected PropertyXamlMember(string attachablePropertyName,
|
|
|
+ MethodInfo getter, MethodInfo setter, XamlSchemaContext schemaContext)
|
|
|
+ : base(attachablePropertyName, getter, setter, schemaContext)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ public PropertyXamlMember(
|
|
|
+ PropertyInfo propertyInfo,
|
|
|
+ XamlSchemaContext schemaContext) :
|
|
|
+ base(propertyInfo, schemaContext)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override MethodInfo LookupUnderlyingSetter()
|
|
|
+ {
|
|
|
+ //if we have content property a list
|
|
|
+ //we have some issues in portable.xaml
|
|
|
+ //but if the list is read only, this is solving the problem
|
|
|
+ //TODO: investigate is this good enough as solution ???
|
|
|
+ //We can add ReadOnyAttribute to cover this
|
|
|
+ if ((Type.IsCollection || Type.IsDictionary) &&
|
|
|
+ Name == DeclaringType.ContentProperty?.Name)
|
|
|
+ {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return base.LookupUnderlyingSetter();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class AvaloniaPropertyXamlMember : PropertyXamlMember
|
|
|
{
|
|
|
public bool AssignBinding { get; set; } = false;
|
|
|
|
|
|
public AvaloniaProperty Property { get; }
|
|
|
|
|
|
+ protected AvaloniaPropertyXamlMember(AvaloniaProperty property,
|
|
|
+ string attachablePropertyName,
|
|
|
+ MethodInfo getter, MethodInfo setter, XamlSchemaContext schemaContext)
|
|
|
+ : base(attachablePropertyName, getter, setter, schemaContext)
|
|
|
+ {
|
|
|
+ Property = property;
|
|
|
+ }
|
|
|
+
|
|
|
public AvaloniaPropertyXamlMember(AvaloniaProperty property,
|
|
|
PropertyInfo propertyInfo,
|
|
|
XamlSchemaContext schemaContext) :
|
|
|
@@ -48,6 +124,16 @@ namespace Avalonia.Markup.Xaml.PortableXaml
|
|
|
return new AvaloniaPropertyInvoker(this);
|
|
|
}
|
|
|
|
|
|
+ protected override bool LookupIsReadOnly()
|
|
|
+ {
|
|
|
+ if (Property.IsReadOnly)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return base.LookupIsReadOnly();
|
|
|
+ }
|
|
|
+
|
|
|
private class AvaloniaPropertyInvoker : XamlMemberInvoker
|
|
|
{
|
|
|
public AvaloniaPropertyInvoker(XamlMember member) : base(member)
|
|
|
@@ -59,9 +145,14 @@ namespace Avalonia.Markup.Xaml.PortableXaml
|
|
|
if (Property != null)
|
|
|
{
|
|
|
var obj = ((IAvaloniaObject)instance);
|
|
|
- if (value is IBinding && !Member.AssignBinding)
|
|
|
+ if (value is IBinding)
|
|
|
{
|
|
|
- ApplyBinding(obj, (IBinding)value);
|
|
|
+ if (!Member.AssignBinding)
|
|
|
+ ApplyBinding(obj, (IBinding)value);
|
|
|
+ else
|
|
|
+ obj.SetValue(Property, value is XamlBinding ?
|
|
|
+ (value as XamlBinding).Value :
|
|
|
+ value);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -86,11 +177,23 @@ namespace Avalonia.Markup.Xaml.PortableXaml
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void ApplyBinding(IAvaloniaObject obj, IBinding binding)
|
|
|
+ public void ApplyBinding(IAvaloniaObject obj, IBinding binding)
|
|
|
{
|
|
|
- //TODO: in Context.PropertyAccessor there is
|
|
|
- //some quirk stuff check it later
|
|
|
- obj.Bind(Property, binding);
|
|
|
+ var control = obj as IControl;
|
|
|
+ var property = Property;
|
|
|
+ var xamlBinding = binding as XamlBinding;
|
|
|
+ //if (control != null && property != Control.DataContextProperty)
|
|
|
+ // DelayedBinding.Add(control, property, binding);
|
|
|
+ //else
|
|
|
+ if (xamlBinding != null)
|
|
|
+ obj.Bind(property, xamlBinding.Value, xamlBinding.Anchor?.Target);
|
|
|
+ else
|
|
|
+ obj.Bind(property, binding);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void SetValue(ITypeDescriptorContext context, object instance, object value)
|
|
|
+ {
|
|
|
+ throw new NotImplementedException();
|
|
|
}
|
|
|
|
|
|
private AvaloniaProperty Property => Member.Property;
|
|
|
@@ -100,7 +203,27 @@ namespace Avalonia.Markup.Xaml.PortableXaml
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public class DependOnXamlMember : XamlMember
|
|
|
+ public class AvaloniaAttachedPropertyXamlMember : AvaloniaPropertyXamlMember
|
|
|
+ {
|
|
|
+ private MethodInfo _setter;
|
|
|
+
|
|
|
+ public AvaloniaAttachedPropertyXamlMember(AvaloniaProperty property,
|
|
|
+ string attachablePropertyName,
|
|
|
+ MethodInfo getter, MethodInfo setter,
|
|
|
+ XamlSchemaContext schemaContext)
|
|
|
+ : base(property, attachablePropertyName, getter, setter, schemaContext)
|
|
|
+ {
|
|
|
+ _setter = setter;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override MethodInfo LookupUnderlyingSetter()
|
|
|
+ {
|
|
|
+ //TODO: investigate don't call base stack overflow
|
|
|
+ return _setter;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class DependOnXamlMember : PropertyXamlMember
|
|
|
{
|
|
|
private string _dependOn;
|
|
|
|
|
|
@@ -157,6 +280,10 @@ namespace Avalonia.Markup.Xaml.PortableXaml
|
|
|
value = ttConv.ConvertFromString(value as string);
|
|
|
}
|
|
|
}
|
|
|
+ if (value is XamlBinding)
|
|
|
+ {
|
|
|
+ value = (value as XamlBinding).Value;
|
|
|
+ }
|
|
|
|
|
|
base.SetValue(instance, value);
|
|
|
}
|