committed by
Andrey Kunchev
11 changed files with 378 additions and 7 deletions
@ -0,0 +1,71 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Reflection; |
||||
|
using Avalonia.Markup.Xaml.Converters; |
||||
|
using Avalonia.Media; |
||||
|
using Avalonia.Media.Imaging; |
||||
|
using Avalonia.Styling; |
||||
|
|
||||
|
namespace Avalonia.Markup.Xaml.PortableXaml |
||||
|
{ |
||||
|
public class AvaloniaDefaultTypeConverters |
||||
|
{ |
||||
|
private static Dictionary<Type, Type> _defaultConverters = new Dictionary<Type, Type>() |
||||
|
{ |
||||
|
{ typeof(IBitmap), typeof(BitmapTypeConverter)}, |
||||
|
{ typeof(IBrush), typeof(BrushTypeConverter) }, |
||||
|
//{ typeof(Color), typeof(ColorTypeConverter) },
|
||||
|
//{ typeof(Classes), typeof(ClassesTypeConverter) },
|
||||
|
//{ typeof(ColumnDefinitions), typeof(ColumnDefinitionsTypeConverter) },
|
||||
|
//{ typeof(DateTime), typeof(DateTimeTypeConverter) },
|
||||
|
//{ typeof(Geometry), typeof(GeometryTypeConverter) },
|
||||
|
//{ typeof(GridLength), typeof(GridLengthTypeConverter) },
|
||||
|
//{ typeof(KeyGesture), typeof(KeyGestureConverter) },
|
||||
|
//{ typeof(AvaloniaList<double>), typeof(AvaloniaListTypeConverter<double>) },
|
||||
|
//{ typeof(IMemberSelector), typeof(MemberSelectorTypeConverter) },
|
||||
|
//{ typeof(Point), typeof(PointTypeConverter) },
|
||||
|
//{ typeof(IList<Point>), typeof(PointsListTypeConverter) },
|
||||
|
{ typeof(AvaloniaProperty), typeof(AvaloniaPropertyTypeConverter) }, |
||||
|
//{ typeof(RelativePoint), typeof(RelativePointTypeConverter) },
|
||||
|
//{ typeof(RelativeRect), typeof(RelativeRectTypeConverter) },
|
||||
|
//{ typeof(RowDefinitions), typeof(RowDefinitionsTypeConverter) },
|
||||
|
//{ typeof(Size), typeof(SizeTypeConverter) },
|
||||
|
{ typeof(Selector), typeof(SelectorTypeConverter)}, |
||||
|
//{ typeof(SolidColorBrush), typeof(BrushTypeConverter) },
|
||||
|
//{ typeof(Thickness), typeof(ThicknessTypeConverter) },
|
||||
|
//{ typeof(TimeSpan), typeof(TimeSpanTypeConverter) },
|
||||
|
//{ typeof(Uri), typeof(Converters.UriTypeConverter) },
|
||||
|
//{ typeof(Cursor), typeof(CursorTypeConverter) },
|
||||
|
//{ typeof(WindowIcon), typeof(IconTypeConverter) },
|
||||
|
//{ typeof(FontWeight), typeof(FontWeightConverter) },
|
||||
|
}; |
||||
|
|
||||
|
public static Type GetTypeConverter(Type type) |
||||
|
{ |
||||
|
Type converterType; |
||||
|
|
||||
|
Type curType = type; |
||||
|
|
||||
|
while (curType != null) |
||||
|
{ |
||||
|
if (_defaultConverters.TryGetValue(curType, out converterType)) |
||||
|
{ |
||||
|
if (curType != type) |
||||
|
{ |
||||
|
_defaultConverters[curType] = converterType; |
||||
|
} |
||||
|
|
||||
|
return converterType; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
_defaultConverters[curType] = null; |
||||
|
} |
||||
|
|
||||
|
curType = curType.GetTypeInfo().BaseType; |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,94 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Reflection; |
||||
|
using Portable.Xaml; |
||||
|
using Portable.Xaml.Schema; |
||||
|
using am = Avalonia.Metadata; |
||||
|
|
||||
|
namespace Avalonia.Markup.Xaml.PortableXaml |
||||
|
{ |
||||
|
public class AvaloniaXamlType : XamlType |
||||
|
{ |
||||
|
public AvaloniaXamlType(Type underlyingType, XamlSchemaContext schemaContext) : |
||||
|
base(underlyingType, schemaContext) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
protected override XamlMember LookupMember(string name, bool skipReadOnlyCheck) |
||||
|
{ |
||||
|
var pi = UnderlyingType.GetRuntimeProperty(name); |
||||
|
|
||||
|
var dependAttr = pi.GetCustomAttribute<am.DependsOnAttribute>(); |
||||
|
|
||||
|
if (dependAttr != null) |
||||
|
{ |
||||
|
return new DependOnXamlMember(dependAttr.Name, pi, SchemaContext); |
||||
|
} |
||||
|
|
||||
|
return base.LookupMember(name, skipReadOnlyCheck); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class DependOnXamlMember : XamlMember |
||||
|
{ |
||||
|
private string _dependOn; |
||||
|
|
||||
|
public DependOnXamlMember(string dependOn, |
||||
|
PropertyInfo propertyInfo, |
||||
|
XamlSchemaContext schemaContext) : |
||||
|
base(propertyInfo, schemaContext) |
||||
|
{ |
||||
|
_dependOn = dependOn; |
||||
|
} |
||||
|
|
||||
|
private XamlMember _dependOnMember; |
||||
|
|
||||
|
public XamlMember DependOnMember |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return _dependOnMember ?? |
||||
|
(_dependOnMember = DeclaringType.GetMember(_dependOn)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected override IList<XamlMember> LookupDependsOn() |
||||
|
{ |
||||
|
return new List<XamlMember>() { DeclaringType.GetMember(_dependOn) }; |
||||
|
} |
||||
|
|
||||
|
protected override XamlMemberInvoker LookupInvoker() |
||||
|
{ |
||||
|
return new DependOnInvoker(this); |
||||
|
} |
||||
|
|
||||
|
private class DependOnInvoker : XamlMemberInvoker |
||||
|
{ |
||||
|
public DependOnInvoker(XamlMember member) : base(member) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public override void SetValue(object instance, object value) |
||||
|
{ |
||||
|
if (value is string && |
||||
|
(Member.UnderlyingMember as PropertyInfo).PropertyType != typeof(string)) |
||||
|
{ |
||||
|
var dpm = (Member as DependOnXamlMember).DependOnMember.UnderlyingMember; |
||||
|
var pi = (dpm as PropertyInfo); |
||||
|
var avp = pi.GetValue(instance) as AvaloniaProperty; |
||||
|
|
||||
|
Type targetType = avp != null ? avp.PropertyType : pi.PropertyType; |
||||
|
|
||||
|
var xamTargetType = Member.DeclaringType.SchemaContext.GetXamlType(targetType); |
||||
|
var ttConv = xamTargetType?.TypeConverter?.ConverterInstance; |
||||
|
if (ttConv != null) |
||||
|
{ |
||||
|
value = ttConv.ConvertFromString(value as string); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
base.SetValue(instance, value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
using System; |
||||
|
using Portable.Xaml.Markup; |
||||
|
|
||||
|
namespace Portable.Xaml.ComponentModel |
||||
|
{ |
||||
|
internal static class TypeDescriptorExtensions |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the service from ITypeDescriptorContext
|
||||
|
/// usually in TypeConverter in xaml reader context
|
||||
|
/// examples:
|
||||
|
/// context.GetService<IXamlTypeResolver>()
|
||||
|
/// context.GetService<IXamlNamespaceResolver>()
|
||||
|
/// context.GetService<IXamlNameProvider>()
|
||||
|
/// context.GetService<INamespacePrefixLookup>()
|
||||
|
/// context.GetService<IXamlSchemaContextProvider>()
|
||||
|
/// context.GetService<IRootObjectProvider>()
|
||||
|
/// context.GetService<IProvideValueTarget>()
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">Service Type</typeparam>
|
||||
|
/// <param name="ctx">The TypeDescriptor context.</param>
|
||||
|
/// <returns></returns>
|
||||
|
public static T GetService<T>(this ITypeDescriptorContext ctx) where T : class |
||||
|
{ |
||||
|
return ctx.GetService(typeof(T)) as T; |
||||
|
} |
||||
|
|
||||
|
public static Type ResolveType(this ITypeDescriptorContext ctx, string namespacePrefix, string type) |
||||
|
{ |
||||
|
var tr = ctx.GetService<IXamlTypeResolver>(); |
||||
|
|
||||
|
string name = string.IsNullOrEmpty(namespacePrefix) ? type : $"{namespacePrefix}:{type}"; |
||||
|
|
||||
|
return tr?.Resolve(name); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue