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