Removed legacy XAML loader
This commit is contained in:
@@ -1,6 +1,3 @@
|
||||
[submodule "src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github"]
|
||||
path = src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github
|
||||
url = https://github.com/AvaloniaUI/Portable.Xaml.git
|
||||
[submodule "nukebuild/Numerge"]
|
||||
path = nukebuild/Numerge
|
||||
url = https://github.com/kekekeks/Numerge.git
|
||||
|
||||
@@ -9,7 +9,6 @@ using Avalonia.Remote.Protocol;
|
||||
using Avalonia.Remote.Protocol.Designer;
|
||||
using Avalonia.Remote.Protocol.Viewport;
|
||||
using Avalonia.Threading;
|
||||
using Portable.Xaml;
|
||||
|
||||
namespace Avalonia.DesignerSupport.Remote
|
||||
{
|
||||
@@ -206,7 +205,6 @@ namespace Avalonia.DesignerSupport.Remote
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var xamlException = e as XamlException;
|
||||
var xmlException = e as XmlException;
|
||||
|
||||
s_transport.Send(new UpdateXamlResultMessage
|
||||
@@ -216,8 +214,8 @@ namespace Avalonia.DesignerSupport.Remote
|
||||
{
|
||||
ExceptionType = e.GetType().FullName,
|
||||
Message = e.Message.ToString(),
|
||||
LineNumber = xamlException?.LineNumber ?? xmlException?.LineNumber,
|
||||
LinePosition = xamlException?.LinePosition ?? xmlException?.LinePosition,
|
||||
LineNumber = xmlException?.LineNumber,
|
||||
LinePosition = xmlException?.LinePosition,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -11,12 +11,8 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="AvaloniaXamlLoader.cs" />
|
||||
<Compile Include="Converters\AvaloniaUriTypeConverter.cs" />
|
||||
<Compile Include="Converters\AvaloniaEventConverter.cs" />
|
||||
<Compile Include="Converters\FontFamilyTypeConverter.cs" />
|
||||
<Compile Include="Converters\MemberSelectorTypeConverter.cs" />
|
||||
<Compile Include="Converters\NullableTypeConverter.cs" />
|
||||
<Compile Include="Converters\ParseTypeConverter.cs" />
|
||||
<Compile Include="Converters\SetterValueTypeConverter.cs" />
|
||||
<Compile Include="Converters\TimeSpanTypeConverter.cs" />
|
||||
<Compile Include="Extensions.cs" />
|
||||
<Compile Include="MarkupExtensions\DynamicResourceExtension.cs" />
|
||||
@@ -24,25 +20,12 @@
|
||||
<Compile Include="MarkupExtensions\StaticResourceExtension.cs" />
|
||||
<Compile Include="MarkupExtensions\StyleIncludeExtension.cs" />
|
||||
<Compile Include="Parsers\PropertyParser.cs" />
|
||||
<Compile Include="PortableXaml\AvaloniaResourceXamlInfo.cs" />
|
||||
<Compile Include="PortableXaml\AvaloniaXamlContext.cs" />
|
||||
<Compile Include="PortableXaml\AttributeExtensions.cs" />
|
||||
<Compile Include="PortableXaml\AvaloniaMemberAttributeProvider.cs" />
|
||||
<Compile Include="PortableXaml\AvaloniaNameScope.cs" />
|
||||
<Compile Include="AvaloniaTypeConverters.cs" />
|
||||
<Compile Include="PortableXaml\AvaloniaXamlObjectWriter.cs" />
|
||||
<Compile Include="PortableXaml\AvaloniaRuntimeTypeProvider.cs" />
|
||||
<Compile Include="PortableXaml\AvaloniaXamlSchemaContext.cs" />
|
||||
<Compile Include="Converters\BitmapTypeConverter.cs" />
|
||||
<Compile Include="Converters\IconTypeConverter.cs" />
|
||||
<Compile Include="Converters\AvaloniaPropertyTypeConverter.cs" />
|
||||
<Compile Include="Converters\PointsListTypeConverter.cs" />
|
||||
<Compile Include="Converters\SelectorTypeConverter.cs" />
|
||||
<Compile Include="MarkupExtensions\BindingExtension.cs" />
|
||||
<Compile Include="MarkupExtensions\RelativeSourceExtension.cs" />
|
||||
<Compile Include="PortableXaml\AvaloniaTypeAttributeProvider.cs" />
|
||||
<Compile Include="PortableXaml\AvaloniaXamlType.cs" />
|
||||
<Compile Include="PortableXaml\TypeDescriptorExtensions.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Styling\StyleInclude.cs" />
|
||||
<Compile Include="Templates\ControlTemplate.cs" />
|
||||
@@ -52,7 +35,6 @@
|
||||
<Compile Include="Templates\MemberSelector.cs" />
|
||||
<Compile Include="Templates\Template.cs" />
|
||||
<Compile Include="Templates\TemplateContent.cs" />
|
||||
<Compile Include="Templates\TemplateLoader.cs" />
|
||||
<Compile Include="Templates\TreeDataTemplate.cs" />
|
||||
<Compile Include="XamlIl\AvaloniaXamlIlRuntimeCompiler.cs" />
|
||||
<Compile Include="XamlIl\CompilerExtensions\Transformers\AvaloniaBindingExtensionHackTransformer.cs" />
|
||||
@@ -76,11 +58,11 @@
|
||||
<Compile Include="XamlIl\Runtime\IAvaloniaXamlIlXmlNamespaceInfoProviderV1.cs" />
|
||||
<Compile Include="XamlIl\Runtime\XamlIlRuntimeHelpers.cs" />
|
||||
<Compile Include="XamlLoadException.cs" />
|
||||
<Compile Include="PortableXaml\portable.xaml.github\src\Portable.Xaml\**\*.cs" Exclude="PortableXaml\portable.xaml.github\src\Portable.Xaml\Assembly\**\*.cs" />
|
||||
<Compile Include="XamlIl\xamlil.github\src\XamlIl\**\*.cs" />
|
||||
<Compile Condition="$(UseCecil) == true" Include="XamlIl\xamlil.github\src\XamlIl.Cecil\**\*.cs" />
|
||||
<Compile Remove="XamlIl\xamlil.github\**\obj\**\*.cs" />
|
||||
<Compile Include="..\Avalonia.Markup\Markup\Parsers\SelectorGrammar.cs" />
|
||||
<Compile Include="XamlTypes.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Avalonia.Animation\Avalonia.Animation.csproj" />
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml.Converters;
|
||||
using Avalonia.Media.Imaging;
|
||||
using Avalonia.Styling;
|
||||
using Avalonia.Controls.Templates;
|
||||
|
||||
namespace Avalonia.Markup.Xaml
|
||||
{
|
||||
using System.Reflection;
|
||||
using Avalonia.Media;
|
||||
|
||||
/// <summary>
|
||||
/// Maintains a repository of <see cref="TypeConverter"/>s for XAML parsing on top of those
|
||||
/// maintained by <see cref="TypeDescriptor"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default method of defining type converters using <see cref="TypeConverterAttribute"/>
|
||||
/// isn't powerful enough for our purposes:
|
||||
///
|
||||
/// - It doesn't handle non-constructed generic types (such as <see cref="AvaloniaList{T}"/>)
|
||||
/// - Type converters which require XAML features cannot be defined in non-XAML assemblies and
|
||||
/// so can't be referenced using <see cref="TypeConverterAttribute"/>
|
||||
/// - Many types have a static `Parse(string)` method which can be used implicitly; this class
|
||||
/// detects such methods and auto-creates a type converter
|
||||
/// </remarks>
|
||||
public static class AvaloniaTypeConverters
|
||||
{
|
||||
// When adding item to that list make sure to modify AvaloniaXamlIlLanguage
|
||||
private static Dictionary<Type, Type> _converters = new Dictionary<Type, Type>()
|
||||
{
|
||||
{ typeof(AvaloniaList<>), typeof(AvaloniaListConverter<>) },
|
||||
{ typeof(AvaloniaProperty), typeof(AvaloniaPropertyTypeConverter) },
|
||||
{ typeof(IBitmap), typeof(BitmapTypeConverter) },
|
||||
{ typeof(IList<Point>), typeof(PointsListTypeConverter) },
|
||||
{ typeof(IMemberSelector), typeof(MemberSelectorTypeConverter) },
|
||||
{ typeof(Selector), typeof(SelectorTypeConverter) },
|
||||
{ typeof(TimeSpan), typeof(TimeSpanTypeConverter) },
|
||||
{ typeof(WindowIcon), typeof(IconTypeConverter) },
|
||||
{ typeof(CultureInfo), typeof(CultureInfoConverter) },
|
||||
{ typeof(Uri), typeof(AvaloniaUriTypeConverter) },
|
||||
{ typeof(FontFamily), typeof(FontFamilyTypeConverter) },
|
||||
{ typeof(EventInfo), typeof(AvaloniaEventConverter) },
|
||||
};
|
||||
|
||||
internal static Type GetBuiltinTypeConverter(Type type)
|
||||
{
|
||||
_converters.TryGetValue(type, out var result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to lookup a <see cref="TypeConverter"/> for a type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns>The type converter.</returns>
|
||||
public static Type GetTypeConverter(Type type)
|
||||
{
|
||||
if (type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
|
||||
{
|
||||
var inner = GetTypeConverter(type.GetGenericArguments()[0]);
|
||||
if (inner == null)
|
||||
return null;
|
||||
return typeof(NullableTypeConverter<>).MakeGenericType(inner);
|
||||
}
|
||||
|
||||
if (_converters.TryGetValue(type, out var result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// Converters for non-constructed generic types can't be specified using
|
||||
// TypeConverterAttribute. Allow them to be registered here and handle them sanely.
|
||||
if (type.IsConstructedGenericType &&
|
||||
_converters.TryGetValue(type.GetGenericTypeDefinition(), out result))
|
||||
{
|
||||
return result?.MakeGenericType(type.GetGenericArguments());
|
||||
}
|
||||
|
||||
// If the type isn't a primitive or a type that XAML already handles, but has a static
|
||||
// Parse method, use that
|
||||
if (!type.IsPrimitive &&
|
||||
type != typeof(DateTime) &&
|
||||
type != typeof(Uri) &&
|
||||
ParseTypeConverter.HasParseMethod(type))
|
||||
{
|
||||
result = typeof(ParseTypeConverter<>).MakeGenericType(type);
|
||||
_converters.Add(type, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
_converters.Add(type, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a type converter for a type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type. Maybe be a non-constructed generic type.</param>
|
||||
/// <param name="converterType">The converter type. Maybe be a non-constructed generic type.</param>
|
||||
public static void Register(Type type, Type converterType) => _converters[type] = converterType;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@ using Avalonia.Controls;
|
||||
using Avalonia.Markup.Data;
|
||||
using Avalonia.Markup.Xaml.PortableXaml;
|
||||
using Avalonia.Platform;
|
||||
using Portable.Xaml;
|
||||
|
||||
namespace Avalonia.Markup.Xaml
|
||||
{
|
||||
@@ -26,71 +25,14 @@ namespace Avalonia.Markup.Xaml
|
||||
{
|
||||
public bool IsDesignMode { get; set; }
|
||||
|
||||
public static bool UseLegacyXamlLoader { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AvaloniaXamlLoader"/> class.
|
||||
/// </summary>
|
||||
public AvaloniaXamlLoader()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the XAML into a Avalonia component.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to load the XAML into.</param>
|
||||
public static void Load(object obj)
|
||||
{
|
||||
Contract.Requires<ArgumentNullException>(obj != null);
|
||||
|
||||
var loader = new AvaloniaXamlLoader();
|
||||
loader.Load(obj.GetType(), obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the XAML for a type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="rootInstance">
|
||||
/// The optional instance into which the XAML should be loaded.
|
||||
/// </param>
|
||||
/// <returns>The loaded object.</returns>
|
||||
public object Load(Type type, object rootInstance = null)
|
||||
{
|
||||
Contract.Requires<ArgumentNullException>(type != null);
|
||||
|
||||
// HACK: Currently Visual Studio is forcing us to change the extension of xaml files
|
||||
// in certain situations, so we try to load .xaml and if that's not found we try .xaml.
|
||||
// Ideally we'd be able to use .xaml everywhere
|
||||
var assetLocator = AvaloniaLocator.Current.GetService<IAssetLoader>();
|
||||
|
||||
if (assetLocator == null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Could not create IAssetLoader : maybe Application.RegisterServices() wasn't called?");
|
||||
}
|
||||
|
||||
foreach (var uri in GetUrisFor(assetLocator, type))
|
||||
{
|
||||
if (assetLocator.Exists(uri))
|
||||
{
|
||||
using (var stream = assetLocator.Open(uri))
|
||||
{
|
||||
var initialize = rootInstance as ISupportInitialize;
|
||||
initialize?.BeginInit();
|
||||
try
|
||||
{
|
||||
return Load(stream, type.Assembly, rootInstance, uri);
|
||||
}
|
||||
finally
|
||||
{
|
||||
initialize?.EndInit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new FileNotFoundException("Unable to find view for " + type.FullName);
|
||||
throw new XamlLoadException(
|
||||
$"No precompiled XAML found for {obj.GetType()}, make sure to specify x:Class and include your XAML file as AvaloniaResource");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -100,11 +42,8 @@ namespace Avalonia.Markup.Xaml
|
||||
/// <param name="baseUri">
|
||||
/// A base URI to use if <paramref name="uri"/> is relative.
|
||||
/// </param>
|
||||
/// <param name="rootInstance">
|
||||
/// The optional instance into which the XAML should be loaded.
|
||||
/// </param>
|
||||
/// <returns>The loaded object.</returns>
|
||||
public object Load(Uri uri, Uri baseUri = null, object rootInstance = null)
|
||||
public object Load(Uri uri, Uri baseUri = null)
|
||||
{
|
||||
Contract.Requires<ArgumentNullException>(uri != null);
|
||||
|
||||
@@ -133,7 +72,7 @@ namespace Avalonia.Markup.Xaml
|
||||
using (var stream = asset.stream)
|
||||
{
|
||||
var absoluteUri = uri.IsAbsoluteUri ? uri : new Uri(baseUri, uri);
|
||||
return Load(stream, asset.assembly, rootInstance, absoluteUri);
|
||||
return Load(stream, asset.assembly, null, absoluteUri);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,95 +105,9 @@ namespace Avalonia.Markup.Xaml
|
||||
/// </param>
|
||||
/// <param name="uri">The URI of the XAML</param>
|
||||
/// <returns>The loaded object.</returns>
|
||||
public object Load(Stream stream, Assembly localAssembly, object rootInstance = null, Uri uri = null)
|
||||
{
|
||||
if (!UseLegacyXamlLoader)
|
||||
return AvaloniaXamlIlRuntimeCompiler.Load(stream, localAssembly, rootInstance, uri, IsDesignMode);
|
||||
public object Load(Stream stream, Assembly localAssembly, object rootInstance = null, Uri uri = null)
|
||||
=> AvaloniaXamlIlRuntimeCompiler.Load(stream, localAssembly, rootInstance, uri, IsDesignMode);
|
||||
|
||||
|
||||
var readerSettings = new XamlXmlReaderSettings()
|
||||
{
|
||||
BaseUri = uri,
|
||||
LocalAssembly = localAssembly,
|
||||
ProvideLineInfo = true,
|
||||
};
|
||||
|
||||
var context = IsDesignMode ? AvaloniaXamlSchemaContext.DesignInstance : AvaloniaXamlSchemaContext.Instance;
|
||||
var reader = new XamlXmlReader(stream, context, readerSettings);
|
||||
|
||||
object result = LoadFromReader(
|
||||
reader,
|
||||
AvaloniaXamlContext.For(readerSettings, rootInstance));
|
||||
|
||||
var topLevel = result as TopLevel;
|
||||
|
||||
if (topLevel != null)
|
||||
{
|
||||
DelayedBinding.ApplyBindings(topLevel);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static object LoadFromReader(XamlReader reader, AvaloniaXamlContext context = null, IAmbientProvider parentAmbientProvider = null)
|
||||
{
|
||||
var writer = AvaloniaXamlObjectWriter.Create(
|
||||
(AvaloniaXamlSchemaContext)reader.SchemaContext,
|
||||
context,
|
||||
parentAmbientProvider);
|
||||
|
||||
XamlServices.Transform(reader, writer);
|
||||
writer.ApplyAllDelayedProperties();
|
||||
return writer.Result;
|
||||
}
|
||||
|
||||
internal static object LoadFromReader(XamlReader reader)
|
||||
{
|
||||
//return XamlServices.Load(reader);
|
||||
return LoadFromReader(reader, null);
|
||||
}
|
||||
|
||||
|
||||
private static readonly DataContractSerializer s_xamlInfoSerializer =
|
||||
new DataContractSerializer(typeof(AvaloniaResourceXamlInfo));
|
||||
/// <summary>
|
||||
/// Gets the URI for a type.
|
||||
/// </summary>
|
||||
/// <param name="assetLocator"></param>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns>The URI.</returns>
|
||||
private static IEnumerable<Uri> GetUrisFor(IAssetLoader assetLocator, Type type)
|
||||
{
|
||||
var asm = type.GetTypeInfo().Assembly.GetName().Name;
|
||||
var xamlInfoUri = new Uri($"avares://{asm}/!AvaloniaResourceXamlInfo");
|
||||
var typeName = type.FullName;
|
||||
if (typeName == null)
|
||||
throw new ArgumentException("Type doesn't have a FullName");
|
||||
|
||||
if (assetLocator.Exists(xamlInfoUri))
|
||||
{
|
||||
using (var xamlInfoStream = assetLocator.Open(xamlInfoUri))
|
||||
{
|
||||
var assetDoc = XDocument.Load(xamlInfoStream);
|
||||
XNamespace assetNs = assetDoc.Root.Attribute("xmlns").Value;
|
||||
XNamespace arrayNs = "http://schemas.microsoft.com/2003/10/Serialization/Arrays";
|
||||
Dictionary<string,string> xamlInfo =
|
||||
assetDoc.Root.Element(assetNs + "ClassToResourcePathIndex").Elements(arrayNs + "KeyValueOfstringstring")
|
||||
.ToDictionary(entry =>entry.Element(arrayNs + "Key").Value,
|
||||
entry => entry.Element(arrayNs + "Value").Value);
|
||||
|
||||
if (xamlInfo.TryGetValue(typeName, out var rv))
|
||||
{
|
||||
yield return new Uri($"avares://{asm}{rv}");
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
yield return new Uri("resm:" + typeName + ".xaml?assembly=" + asm);
|
||||
yield return new Uri("resm:" + typeName + ".paml?assembly=" + asm);
|
||||
}
|
||||
|
||||
public static object Parse(string xaml, Assembly localAssembly = null)
|
||||
=> new AvaloniaXamlLoader().Load(xaml, localAssembly);
|
||||
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml.PortableXaml;
|
||||
using Portable.Xaml;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.Converters
|
||||
{
|
||||
internal class AvaloniaEventConverter : TypeConverter
|
||||
{
|
||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||
{
|
||||
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
|
||||
}
|
||||
|
||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||
{
|
||||
var text = value as string;
|
||||
if (text != null)
|
||||
{
|
||||
var rootObjectProvider = context.GetService(typeof(IRootObjectProvider)) as IRootObjectProvider;
|
||||
var destinationTypeProvider = context.GetService(typeof(IDestinationTypeProvider)) as IDestinationTypeProvider;
|
||||
if (rootObjectProvider != null && destinationTypeProvider != null)
|
||||
{
|
||||
var target = rootObjectProvider.RootObject;
|
||||
var eventType = destinationTypeProvider.GetDestinationType();
|
||||
var eventParameters = eventType.GetRuntimeMethods().First(r => r.Name == "Invoke").GetParameters();
|
||||
// go in reverse to match System.Xaml behaviour
|
||||
var methods = target.GetType().GetRuntimeMethods().Reverse();
|
||||
|
||||
// find based on exact match parameter types first
|
||||
foreach (var method in methods)
|
||||
{
|
||||
if (method.Name != text)
|
||||
continue;
|
||||
var parameters = method.GetParameters();
|
||||
if (eventParameters.Length != parameters.Length)
|
||||
continue;
|
||||
if (parameters.Length == 0)
|
||||
return method.CreateDelegate(eventType, target);
|
||||
|
||||
for (int i = 0; i < parameters.Length; i++)
|
||||
{
|
||||
var param = parameters[i];
|
||||
var eventParam = eventParameters[i];
|
||||
if (param.ParameterType != eventParam.ParameterType)
|
||||
break;
|
||||
if (i == parameters.Length - 1)
|
||||
return method.CreateDelegate(eventType, target);
|
||||
}
|
||||
}
|
||||
|
||||
// EnhancedXaml: Find method with compatible base class parameters
|
||||
foreach (var method in methods)
|
||||
{
|
||||
if (method.Name != text)
|
||||
continue;
|
||||
var parameters = method.GetParameters();
|
||||
if (parameters.Length == 0 || eventParameters.Length != parameters.Length)
|
||||
continue;
|
||||
|
||||
for (int i = 0; i < parameters.Length; i++)
|
||||
{
|
||||
var param = parameters[i];
|
||||
var eventParam = eventParameters[i];
|
||||
if (!param.ParameterType.GetTypeInfo().IsAssignableFrom(eventParam.ParameterType.GetTypeInfo()))
|
||||
break;
|
||||
if (i == parameters.Length - 1)
|
||||
return method.CreateDelegate(eventType, target);
|
||||
}
|
||||
}
|
||||
|
||||
var contextProvider = (IXamlSchemaContextProvider)context.GetService(typeof(IXamlSchemaContextProvider));
|
||||
var avaloniaContext = (AvaloniaXamlSchemaContext)contextProvider.SchemaContext;
|
||||
|
||||
if (avaloniaContext.IsDesignMode)
|
||||
{
|
||||
// We want to ignore missing events in the designer, so if event handler
|
||||
// wasn't found create an empty delegate.
|
||||
var lambdaExpression = Expression.Lambda(
|
||||
eventType,
|
||||
Expression.Empty(),
|
||||
eventParameters.Select(x => Expression.Parameter(x.ParameterType)));
|
||||
return lambdaExpression.Compile();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new XamlObjectWriterException($"Referenced value method {text} in type {target.GetType()} indicated by event {eventType.FullName} was not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
return base.ConvertFrom(context, culture, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ using Avalonia.Markup.Xaml.Parsers;
|
||||
using Avalonia.Markup.Xaml.Templates;
|
||||
using Avalonia.Styling;
|
||||
using Avalonia.Utilities;
|
||||
using Portable.Xaml.ComponentModel;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.Converters
|
||||
{
|
||||
|
||||
@@ -8,8 +8,7 @@ using Avalonia.Platform;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.Converters
|
||||
{
|
||||
using Portable.Xaml.ComponentModel;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel;
|
||||
|
||||
public class BitmapTypeConverter : TypeConverter
|
||||
{
|
||||
|
||||
@@ -7,7 +7,6 @@ using System.Globalization;
|
||||
|
||||
using Avalonia.Media;
|
||||
|
||||
using Portable.Xaml.ComponentModel;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.Converters
|
||||
{
|
||||
|
||||
@@ -9,7 +9,6 @@ using System.Globalization;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.Converters
|
||||
{
|
||||
using Portable.Xaml.ComponentModel;
|
||||
using System.ComponentModel;
|
||||
|
||||
public class IconTypeConverter : TypeConverter
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.Converters
|
||||
{
|
||||
public class NullableTypeConverter<T> : TypeConverter where T : TypeConverter, new()
|
||||
{
|
||||
private TypeConverter _inner;
|
||||
|
||||
public NullableTypeConverter()
|
||||
{
|
||||
_inner = new T();
|
||||
}
|
||||
|
||||
public NullableTypeConverter(TypeConverter inner)
|
||||
{
|
||||
_inner = inner;
|
||||
}
|
||||
|
||||
|
||||
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
|
||||
{
|
||||
if (value == null)
|
||||
return null;
|
||||
return _inner.ConvertTo(context, culture, value, destinationType);
|
||||
}
|
||||
|
||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||
{
|
||||
if (value == null)
|
||||
return null;
|
||||
if (value as string == "")
|
||||
return null;
|
||||
return _inner.ConvertFrom(context, culture, value);
|
||||
}
|
||||
|
||||
public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
|
||||
{
|
||||
return _inner.CreateInstance(context, propertyValues);
|
||||
}
|
||||
|
||||
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
|
||||
{
|
||||
return _inner.GetStandardValuesSupported(context);
|
||||
}
|
||||
|
||||
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
|
||||
{
|
||||
return _inner.GetStandardValuesExclusive(context);
|
||||
}
|
||||
|
||||
public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
|
||||
{
|
||||
return _inner.GetCreateInstanceSupported(context);
|
||||
}
|
||||
|
||||
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
|
||||
{
|
||||
return _inner.GetPropertiesSupported(context);
|
||||
}
|
||||
|
||||
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
|
||||
{
|
||||
return _inner.GetStandardValues(context);
|
||||
}
|
||||
|
||||
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
|
||||
{
|
||||
return _inner.GetProperties(context, value, attributes);
|
||||
}
|
||||
|
||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
||||
{
|
||||
return _inner.CanConvertTo(context, destinationType);
|
||||
}
|
||||
|
||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||
{
|
||||
return _inner.CanConvertFrom(context, sourceType);
|
||||
}
|
||||
|
||||
public override bool IsValid(ITypeDescriptorContext context, object value)
|
||||
{
|
||||
return _inner.IsValid(context, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for type converters which call a static Parse method.
|
||||
/// </summary>
|
||||
public abstract class ParseTypeConverter : TypeConverter
|
||||
{
|
||||
protected const BindingFlags PublicStatic = BindingFlags.Public | BindingFlags.Static;
|
||||
protected static readonly Type[] StringParameter = new[] { typeof(string) };
|
||||
protected static readonly Type[] StringIFormatProviderParameters = new[] { typeof(string), typeof(IFormatProvider) };
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether a type has a suitable Parse method.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns>True if the type has a suitable parse method, otherwise false.</returns>
|
||||
public static bool HasParseMethod(Type type)
|
||||
{
|
||||
return type.GetMethod("Parse", PublicStatic, null, StringIFormatProviderParameters, null) != null ||
|
||||
type.GetMethod("Parse", PublicStatic, null, StringParameter, null) != null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A type converter which calls a static Parse method.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type with the Parse method.</typeparam>
|
||||
public class ParseTypeConverter<T> : ParseTypeConverter
|
||||
{
|
||||
private static Func<string, T> _parse;
|
||||
private static Func<string, IFormatProvider, T> _parseWithFormat;
|
||||
|
||||
static ParseTypeConverter()
|
||||
{
|
||||
var method = typeof(T).GetMethod("Parse", PublicStatic, null, StringIFormatProviderParameters, null);
|
||||
|
||||
if (method != null)
|
||||
{
|
||||
_parseWithFormat = (Func<string, IFormatProvider, T>)method
|
||||
.CreateDelegate(typeof(Func<string, IFormatProvider, T>));
|
||||
return;
|
||||
}
|
||||
|
||||
method = typeof(T).GetMethod("Parse", PublicStatic, null, StringParameter, null);
|
||||
|
||||
if (method != null)
|
||||
{
|
||||
_parse = (Func<string, T>)method.CreateDelegate(typeof(Func<string, T>));
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||
{
|
||||
return sourceType == typeof(string);
|
||||
}
|
||||
|
||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
if (_parse != null)
|
||||
{
|
||||
return _parse(value.ToString());
|
||||
}
|
||||
else if (_parseWithFormat != null)
|
||||
{
|
||||
return _parseWithFormat(value.ToString(), culture);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// 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 System.Globalization;
|
||||
using Avalonia.Markup.Parsers;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.Converters
|
||||
{
|
||||
using Portable.Xaml.ComponentModel;
|
||||
using System.ComponentModel;
|
||||
|
||||
public class SelectorTypeConverter : TypeConverter
|
||||
{
|
||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||
{
|
||||
return sourceType == typeof(string);
|
||||
}
|
||||
|
||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||
{
|
||||
var parser = new SelectorParser(context.ResolveType);
|
||||
|
||||
return parser.Parse((string)value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
// 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 Avalonia.Styling;
|
||||
using Portable.Xaml;
|
||||
using Portable.Xaml.ComponentModel;
|
||||
using System.ComponentModel;
|
||||
using Portable.Xaml.Markup;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.Converters
|
||||
{
|
||||
public class SetterValueTypeConverter : TypeConverter
|
||||
{
|
||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||
{
|
||||
return sourceType == typeof(string);
|
||||
}
|
||||
|
||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||
{
|
||||
object setter = context.GetService<IProvideValueTarget>().TargetObject;
|
||||
var schemaContext = context.GetService<IXamlSchemaContextProvider>().SchemaContext;
|
||||
|
||||
return ConvertSetterValue(context, schemaContext, culture, (setter as Setter), value);
|
||||
}
|
||||
|
||||
[Obsolete("TODO: try assosiate Setter.Value property with SetterValueTypeConverter, so far coouldn't make it :(")]
|
||||
internal static object ConvertSetterValue(ITypeDescriptorContext dcontext, XamlSchemaContext context, CultureInfo info, Setter setter, object value)
|
||||
{
|
||||
Type targetType = setter?.Property?.PropertyType;
|
||||
|
||||
if (targetType == null)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
var ttConv = context.GetXamlType(targetType)?.TypeConverter?.ConverterInstance;
|
||||
|
||||
if (ttConv != null)
|
||||
{
|
||||
value = ttConv.ConvertFromString(dcontext, info, value as string);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,6 @@ using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Avalonia.Markup.Xaml.XamlIl.Runtime;
|
||||
using Portable.Xaml;
|
||||
using Portable.Xaml.Markup;
|
||||
|
||||
namespace Avalonia.Markup.Xaml
|
||||
{
|
||||
@@ -13,42 +11,19 @@ namespace Avalonia.Markup.Xaml
|
||||
public static T GetService<T>(this IServiceProvider sp) => (T)sp?.GetService(typeof(T));
|
||||
|
||||
|
||||
public static Uri GetContextBaseUri(this IServiceProvider ctx)
|
||||
{
|
||||
var properService = ctx.GetService<IUriContext>();
|
||||
if (properService != null)
|
||||
return properService.BaseUri;
|
||||
// Ugly hack with casts
|
||||
return Portable.Xaml.ComponentModel.TypeDescriptorExtensions.GetBaseUri((ITypeDescriptorContext)ctx);
|
||||
}
|
||||
public static Uri GetContextBaseUri(this IServiceProvider ctx) => ctx.GetService<IUriContext>().BaseUri;
|
||||
|
||||
public static T GetFirstParent<T>(this IServiceProvider ctx) where T : class
|
||||
{
|
||||
var parentStack = ctx.GetService<IAvaloniaXamlIlParentStackProvider>();
|
||||
if (parentStack != null)
|
||||
return parentStack.Parents.OfType<T>().FirstOrDefault();
|
||||
return Portable.Xaml.ComponentModel.TypeDescriptorExtensions.GetFirstAmbientValue<T>((ITypeDescriptorContext)ctx);
|
||||
}
|
||||
|
||||
public static T GetLastParent<T>(this IServiceProvider ctx) where T : class
|
||||
{
|
||||
var parentStack = ctx.GetService<IAvaloniaXamlIlParentStackProvider>();
|
||||
if (parentStack != null)
|
||||
return parentStack.Parents.OfType<T>().LastOrDefault();
|
||||
return Portable.Xaml.ComponentModel.TypeDescriptorExtensions.GetLastOrDefaultAmbientValue<T>(
|
||||
(ITypeDescriptorContext)ctx);
|
||||
}
|
||||
public static T GetFirstParent<T>(this IServiceProvider ctx) where T : class
|
||||
=> ctx.GetService<IAvaloniaXamlIlParentStackProvider>().Parents.OfType<T>().FirstOrDefault();
|
||||
|
||||
public static T GetLastParent<T>(this IServiceProvider ctx) where T : class
|
||||
=> ctx.GetService<IAvaloniaXamlIlParentStackProvider>().Parents.OfType<T>().LastOrDefault();
|
||||
|
||||
public static IEnumerable<T> GetParents<T>(this IServiceProvider sp)
|
||||
{
|
||||
var stack = sp.GetService<IAvaloniaXamlIlParentStackProvider>();
|
||||
if (stack != null)
|
||||
return stack.Parents.OfType<T>();
|
||||
return sp.GetService<IAvaloniaXamlIlParentStackProvider>().Parents.OfType<T>();
|
||||
|
||||
|
||||
var context = (ITypeDescriptorContext)sp;
|
||||
var schemaContext = context.GetService<IXamlSchemaContextProvider>().SchemaContext;
|
||||
var ambientProvider = context.GetService<IAmbientProvider>();
|
||||
return ambientProvider.GetAllAmbientValues(schemaContext.GetXamlType(typeof(T))).OfType<T>();
|
||||
}
|
||||
|
||||
public static Type ResolveType(this IServiceProvider ctx, string namespacePrefix, string type)
|
||||
|
||||
@@ -10,14 +10,9 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
|
||||
using Avalonia.Data.Converters;
|
||||
using Avalonia.Markup.Data;
|
||||
using Avalonia.Styling;
|
||||
using Portable.Xaml;
|
||||
using Portable.Xaml.ComponentModel;
|
||||
using Portable.Xaml.Markup;
|
||||
using PortableXaml;
|
||||
using System.ComponentModel;
|
||||
|
||||
[MarkupExtensionReturnType(typeof(IBinding))]
|
||||
public class BindingExtension : MarkupExtension
|
||||
public class BindingExtension
|
||||
{
|
||||
public BindingExtension()
|
||||
{
|
||||
@@ -28,12 +23,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
|
||||
Path = path;
|
||||
}
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
return ProvideTypedValue(serviceProvider);
|
||||
}
|
||||
|
||||
public Binding ProvideTypedValue(IServiceProvider serviceProvider)
|
||||
public Binding ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
var descriptorContext = (ITypeDescriptorContext)serviceProvider;
|
||||
|
||||
|
||||
@@ -7,13 +7,10 @@ using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Data;
|
||||
using Portable.Xaml;
|
||||
using Portable.Xaml.ComponentModel;
|
||||
using Portable.Xaml.Markup;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.MarkupExtensions
|
||||
{
|
||||
public class DynamicResourceExtension : MarkupExtension, IBinding
|
||||
public class DynamicResourceExtension : IBinding
|
||||
{
|
||||
private IResourceNode _anchor;
|
||||
|
||||
@@ -28,9 +25,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
|
||||
|
||||
public object ResourceKey { get; set; }
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider) => ProvideTypedValue(serviceProvider);
|
||||
|
||||
public IBinding ProvideTypedValue(IServiceProvider serviceProvider)
|
||||
public IBinding ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
var provideTarget = serviceProvider.GetService<IProvideValueTarget>();
|
||||
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
|
||||
using System;
|
||||
using Avalonia.Data;
|
||||
using Portable.Xaml.Markup;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.MarkupExtensions
|
||||
{
|
||||
public class RelativeSourceExtension : MarkupExtension
|
||||
public class RelativeSourceExtension
|
||||
{
|
||||
public RelativeSourceExtension()
|
||||
{
|
||||
@@ -18,7 +17,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
|
||||
Mode = mode;
|
||||
}
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
public RelativeSource ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
return new RelativeSource
|
||||
{
|
||||
@@ -38,4 +37,4 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
|
||||
|
||||
public int AncestorLevel { get; set; } = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using Avalonia.Controls;
|
||||
using Portable.Xaml.ComponentModel;
|
||||
using Portable.Xaml.Markup;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.MarkupExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Loads a resource dictionary from a specified URL.
|
||||
/// </summary>
|
||||
public class ResourceInclude : MarkupExtension, IResourceProvider
|
||||
public class ResourceInclude :IResourceProvider
|
||||
{
|
||||
private Uri _baseUri;
|
||||
private IResourceDictionary _loaded;
|
||||
@@ -52,13 +50,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
|
||||
return Loaded.TryGetResource(key, out value);
|
||||
}
|
||||
|
||||
/// <inhertidoc/>
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
return ProvideTypedValue(serviceProvider);
|
||||
}
|
||||
|
||||
public ResourceInclude ProvideTypedValue(IServiceProvider serviceProvider)
|
||||
public ResourceInclude ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
var tdc = (ITypeDescriptorContext)serviceProvider;
|
||||
_baseUri = tdc?.GetContextBaseUri();
|
||||
|
||||
@@ -7,13 +7,10 @@ using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Data;
|
||||
using Portable.Xaml;
|
||||
using Portable.Xaml.ComponentModel;
|
||||
using Portable.Xaml.Markup;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.MarkupExtensions
|
||||
{
|
||||
public class StaticResourceExtension : MarkupExtension
|
||||
public class StaticResourceExtension
|
||||
{
|
||||
public StaticResourceExtension()
|
||||
{
|
||||
@@ -26,26 +23,13 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
|
||||
|
||||
public string ResourceKey { get; set; }
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
public object ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
|
||||
|
||||
// Look upwards though the ambient context for IResourceProviders which might be able
|
||||
// to give us the resource.
|
||||
foreach (var resourceProvider in serviceProvider.GetParents<IResourceNode>())
|
||||
{
|
||||
// We override XamlType.CanAssignTo in BindingXamlType so the results we get back
|
||||
// from GetAllAmbientValues aren't necessarily of the correct type.
|
||||
|
||||
if (AvaloniaXamlLoader.UseLegacyXamlLoader
|
||||
&& resourceProvider is IControl control && control.StylingParent != null)
|
||||
{
|
||||
// If we've got to a control that has a StylingParent then it's probably
|
||||
// a top level control and its StylingParent is pointing to the global
|
||||
// styles. If this is case just do a FindResource on it.
|
||||
return control.FindResource(ResourceKey);
|
||||
}
|
||||
else if (resourceProvider.TryGetResource(ResourceKey, out var value))
|
||||
if (resourceProvider.TryGetResource(ResourceKey, out var value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -3,23 +3,18 @@
|
||||
|
||||
using Avalonia.Markup.Xaml.Styling;
|
||||
using Avalonia.Styling;
|
||||
using Portable.Xaml;
|
||||
using Portable.Xaml.ComponentModel;
|
||||
using System.ComponentModel;
|
||||
using Portable.Xaml.Markup;
|
||||
using System;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.MarkupExtensions
|
||||
{
|
||||
[MarkupExtensionReturnType(typeof(IStyle))]
|
||||
public class StyleIncludeExtension : MarkupExtension
|
||||
public class StyleIncludeExtension
|
||||
{
|
||||
public StyleIncludeExtension()
|
||||
{
|
||||
}
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider) => ProvideTypedValue(serviceProvider);
|
||||
public IStyle ProvideTypedValue(IServiceProvider serviceProvider)
|
||||
public IStyle ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
return new StyleInclude(serviceProvider.GetContextBaseUri()) { Source = Source };
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
using Avalonia.Markup.Xaml.Templates;
|
||||
using avm = Avalonia.Metadata;
|
||||
using pm = Portable.Xaml.Markup;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.PortableXaml
|
||||
{
|
||||
internal static class AttributeExtensions
|
||||
{
|
||||
public static pm.XamlDeferLoadAttribute ToPortableXaml(this avm.TemplateContentAttribute attrib)
|
||||
{
|
||||
if (attrib == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new pm.XamlDeferLoadAttribute(typeof(TemplateLoader), typeof(TemplateContent));
|
||||
}
|
||||
|
||||
public static pm.AmbientAttribute ToPortableXaml(this avm.AmbientAttribute attrib)
|
||||
{
|
||||
if (attrib == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new pm.AmbientAttribute();
|
||||
}
|
||||
|
||||
public static pm.DependsOnAttribute ToPortableXaml(this avm.DependsOnAttribute attrib)
|
||||
{
|
||||
if (attrib == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new pm.DependsOnAttribute(attrib.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
using Avalonia.Markup.Xaml.Converters;
|
||||
using Avalonia.Styling;
|
||||
using Portable.Xaml.ComponentModel;
|
||||
using System.ComponentModel;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using avm = Avalonia.Metadata;
|
||||
using pm = Portable.Xaml.Markup;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.PortableXaml
|
||||
{
|
||||
public class AvaloniaMemberAttributeProvider : ICustomAttributeProvider
|
||||
{
|
||||
public AvaloniaMemberAttributeProvider(MemberInfo info)
|
||||
{
|
||||
_info = info;
|
||||
}
|
||||
|
||||
public object[] GetCustomAttributes(bool inherit)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public object[] GetCustomAttributes(Type attributeType, bool inherit)
|
||||
{
|
||||
Attribute result = null;
|
||||
|
||||
if (attributeType == typeof(pm.XamlDeferLoadAttribute))
|
||||
{
|
||||
result = _info.GetCustomAttribute<avm.TemplateContentAttribute>(inherit)
|
||||
.ToPortableXaml();
|
||||
}
|
||||
else if (attributeType == typeof(pm.AmbientAttribute))
|
||||
{
|
||||
result = _info.GetCustomAttribute<avm.AmbientAttribute>(inherit)
|
||||
.ToPortableXaml();
|
||||
}
|
||||
else if (attributeType == typeof(pm.DependsOnAttribute))
|
||||
{
|
||||
result = _info.GetCustomAttribute<avm.DependsOnAttribute>(inherit)
|
||||
.ToPortableXaml();
|
||||
}
|
||||
else if (attributeType == typeof(TypeConverterAttribute) &&
|
||||
_info.DeclaringType == typeof(Setter) &&
|
||||
_info.Name == nameof(Setter.Value))
|
||||
{
|
||||
//actually it never comes here looks like if property type is object
|
||||
//Portable.Xaml is not searching for Type Converter
|
||||
result = new TypeConverterAttribute(typeof(SetterValueTypeConverter));
|
||||
}
|
||||
else if (attributeType == typeof(TypeConverterAttribute) && _info is EventInfo)
|
||||
{
|
||||
// If a type converter for `EventInfo` is registered, then use that to convert
|
||||
// event handler values. This is used by the designer to override the lookup
|
||||
// for event handlers with a null handler.
|
||||
var eventConverter = AvaloniaTypeConverters.GetTypeConverter(typeof(EventInfo));
|
||||
|
||||
if (eventConverter != null)
|
||||
{
|
||||
result = new TypeConverterAttribute(eventConverter);
|
||||
}
|
||||
}
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
var attr = _info.GetCustomAttributes(attributeType, inherit);
|
||||
return (attr as object[]) ?? attr.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new object[] { result };
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDefined(Type attributeType, bool inherit)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private readonly MemberInfo _info;
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.PortableXaml
|
||||
{
|
||||
internal class AvaloniaNameScope : Portable.Xaml.Markup.INameScope
|
||||
{
|
||||
public object Instance { get; set; }
|
||||
|
||||
private Dictionary<string, object> _names = new Dictionary<string, object>();
|
||||
|
||||
public object FindName(string name)
|
||||
{
|
||||
object result;
|
||||
if (_names.TryGetValue(name, out result))
|
||||
return result;
|
||||
return null;
|
||||
}
|
||||
|
||||
public void RegisterName(string name, object scopedElement)
|
||||
{
|
||||
if (scopedElement != null)
|
||||
_names.Add(name, scopedElement);
|
||||
|
||||
//TODO: ???
|
||||
//var control = scopedElement as Control;
|
||||
|
||||
//if (control != null)
|
||||
//{
|
||||
// var nameScope = (Instance as INameScope) ?? control.FindNameScope();
|
||||
|
||||
// if (nameScope != null)
|
||||
// {
|
||||
// nameScope.Register(name, scopedElement);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
public void UnregisterName(string name)
|
||||
{
|
||||
}
|
||||
|
||||
public void RegisterOnNameScope(object target)
|
||||
{
|
||||
var nameScope = target as INameScope;
|
||||
|
||||
if (nameScope != null)
|
||||
{
|
||||
foreach (var v in _names)
|
||||
{
|
||||
nameScope.Register(v.Key, v.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
// 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Markup.Xaml.Templates;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Metadata;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.Context
|
||||
{
|
||||
using ClrNamespaceInfo = Tuple<string, Assembly>;
|
||||
|
||||
public interface IRuntimeTypeProvider
|
||||
{
|
||||
Type FindType(string xamlNamespace, string name, Type[] genArgs);
|
||||
|
||||
IEnumerable<Assembly> ReferencedAssemblies { get; }
|
||||
}
|
||||
|
||||
public class AvaloniaRuntimeTypeProvider : IRuntimeTypeProvider
|
||||
{
|
||||
private const string ClrNamespace = "clr-namespace:";
|
||||
// private const string AvaloniaNs = "https://github.com/avaloniaui";
|
||||
|
||||
private static readonly IEnumerable<Assembly> ForcedAssemblies = new[]
|
||||
{
|
||||
typeof(AvaloniaObject).GetTypeInfo().Assembly,
|
||||
typeof(Animation.Animation).GetTypeInfo().Assembly,
|
||||
typeof(Control).GetTypeInfo().Assembly,
|
||||
typeof(Style).GetTypeInfo().Assembly,
|
||||
typeof(DataTemplate).GetTypeInfo().Assembly,
|
||||
typeof(SolidColorBrush).GetTypeInfo().Assembly,
|
||||
typeof(Binding).GetTypeInfo().Assembly,
|
||||
};
|
||||
|
||||
private Dictionary<string, HashSet<ClrNamespaceInfo>> _namespaces = new Dictionary<string, HashSet<ClrNamespaceInfo>>();
|
||||
|
||||
private List<Assembly> _scanned = new List<Assembly>();
|
||||
|
||||
public IEnumerable<Assembly> ReferencedAssemblies => _scanned;
|
||||
|
||||
public AvaloniaRuntimeTypeProvider()
|
||||
{
|
||||
ScanAssemblies(ForcedAssemblies);
|
||||
ScanNewAssemblies();
|
||||
}
|
||||
|
||||
private static bool IsClrNamespace(string ns)
|
||||
{
|
||||
return ns.StartsWith(ClrNamespace);
|
||||
}
|
||||
|
||||
private static Assembly GetAssembly(string assemblyName)
|
||||
{
|
||||
return Assembly.Load(new AssemblyName(assemblyName));
|
||||
}
|
||||
|
||||
private void ScanAssemblies(IEnumerable<Assembly> assemblies)
|
||||
{
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
var namespaces = assembly.GetCustomAttributes<XmlnsDefinitionAttribute>()
|
||||
.Select(x => new { x.XmlNamespace, x.ClrNamespace })
|
||||
.GroupBy(x => x.XmlNamespace);
|
||||
|
||||
foreach (var nsa in namespaces)
|
||||
{
|
||||
HashSet<ClrNamespaceInfo> reg;
|
||||
|
||||
if (!_namespaces.TryGetValue(nsa.Key, out reg))
|
||||
{
|
||||
_namespaces[nsa.Key] = reg = new HashSet<Tuple<string, Assembly>>();
|
||||
}
|
||||
|
||||
foreach (var child in nsa)
|
||||
{
|
||||
reg.Add(new ClrNamespaceInfo(child.ClrNamespace, assembly));
|
||||
}
|
||||
}
|
||||
|
||||
_scanned.Add(assembly);
|
||||
}
|
||||
}
|
||||
|
||||
private void ScanNewAssemblies()
|
||||
{
|
||||
IEnumerable<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
|
||||
if (assemblies != null)
|
||||
{
|
||||
assemblies = assemblies.Except(_scanned);
|
||||
ScanAssemblies(assemblies);
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, Type> _typeCache = new Dictionary<string, Type>();
|
||||
|
||||
public Type FindType(string xamlNamespace, string name, Type[] genArgs)
|
||||
{
|
||||
if (IsClrNamespace(xamlNamespace))
|
||||
{
|
||||
//we need to handle only xaml url namespaces for avalonia,
|
||||
//the other namespaces are handled well in portable.xaml
|
||||
return null;
|
||||
}
|
||||
|
||||
string key = $"{xamlNamespace}:{name}";
|
||||
|
||||
Type type;
|
||||
|
||||
if (_typeCache.TryGetValue(key, out type))
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
HashSet<ClrNamespaceInfo> reg;
|
||||
|
||||
if (!_namespaces.TryGetValue(xamlNamespace, out reg))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (genArgs != null)
|
||||
name += "`" + genArgs.Length;
|
||||
|
||||
foreach (var ns in reg)
|
||||
{
|
||||
var n = ns.Item1 + "." + name;
|
||||
var t = ns.Item2.GetType(n);
|
||||
if (t != null)
|
||||
{
|
||||
_typeCache[key] = t;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
// Copyright (c) The Perspex Project. All rights reserved.
|
||||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
||||
using Portable.Xaml.ComponentModel;
|
||||
using System.ComponentModel;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using avm = Avalonia.Metadata;
|
||||
using pm = Portable.Xaml.Markup;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.PortableXaml
|
||||
{
|
||||
internal class AvaloniaTypeAttributeProvider : ICustomAttributeProvider
|
||||
{
|
||||
public AvaloniaTypeAttributeProvider(Type type)
|
||||
{
|
||||
_type = type;
|
||||
}
|
||||
|
||||
public object[] GetCustomAttributes(bool inherit)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public object[] GetCustomAttributes(Type attributeType, bool inherit)
|
||||
{
|
||||
Attribute result = null;
|
||||
|
||||
var ti = _type.GetTypeInfo();
|
||||
|
||||
if (attributeType == typeof(pm.ContentPropertyAttribute))
|
||||
{
|
||||
result = GetContentPropertyAttribute(inherit);
|
||||
}
|
||||
else if (attributeType == typeof(pm.RuntimeNamePropertyAttribute))
|
||||
{
|
||||
if (_namedType.IsAssignableFrom(ti))
|
||||
{
|
||||
result = new pm.RuntimeNamePropertyAttribute(nameof(INamed.Name));
|
||||
}
|
||||
}
|
||||
else if (attributeType == typeof(TypeConverterAttribute))
|
||||
{
|
||||
var builtin = AvaloniaTypeConverters.GetBuiltinTypeConverter(_type);
|
||||
if (builtin != null)
|
||||
result = new TypeConverterAttribute(builtin);
|
||||
result = result ?? ti.GetCustomAttribute(attributeType, inherit);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
var convType = AvaloniaTypeConverters.GetTypeConverter(_type);
|
||||
|
||||
if (convType != null)
|
||||
{
|
||||
result = new TypeConverterAttribute(convType);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (attributeType == typeof(pm.AmbientAttribute))
|
||||
{
|
||||
result = ti.GetCustomAttribute<avm.AmbientAttribute>(inherit)
|
||||
.ToPortableXaml();
|
||||
}
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
var attr = ti.GetCustomAttributes(attributeType, inherit);
|
||||
return (attr as object[]) ?? attr.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new object[] { result };
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDefined(Type attributeType, bool inherit)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private readonly TypeInfo _namedType = typeof(INamed).GetTypeInfo();
|
||||
|
||||
private readonly Type _type;
|
||||
|
||||
private Attribute GetContentPropertyAttribute(bool inherit)
|
||||
{
|
||||
var type = _type;
|
||||
|
||||
while (type != null)
|
||||
{
|
||||
var properties = type.GetTypeInfo().DeclaredProperties
|
||||
.Where(x => x.GetCustomAttribute<avm.ContentAttribute>() != null);
|
||||
string result = null;
|
||||
|
||||
foreach (var property in properties)
|
||||
{
|
||||
if (result != null)
|
||||
{
|
||||
throw new Exception($"Content property defined more than once on {type}.");
|
||||
}
|
||||
|
||||
result = property.Name;
|
||||
}
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
return new pm.ContentPropertyAttribute(result);
|
||||
}
|
||||
|
||||
type = inherit ? type.GetTypeInfo().BaseType : null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using Portable.Xaml;
|
||||
using Portable.Xaml.Markup;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.PortableXaml
|
||||
{
|
||||
public class AvaloniaXamlContext : IUriContext
|
||||
{
|
||||
private AvaloniaXamlContext()
|
||||
{
|
||||
}
|
||||
|
||||
public Assembly LocalAssembly { get; private set; }
|
||||
|
||||
public Uri BaseUri { get; set; }
|
||||
|
||||
public object RootInstance { get; private set; }
|
||||
|
||||
internal static AvaloniaXamlContext For(XamlXmlReaderSettings sett,
|
||||
object rootInstance)
|
||||
{
|
||||
return new AvaloniaXamlContext()
|
||||
{
|
||||
BaseUri = sett.BaseUri,
|
||||
LocalAssembly = sett.LocalAssembly,
|
||||
RootInstance = rootInstance
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,222 +0,0 @@
|
||||
using Avalonia.Data;
|
||||
using Portable.Xaml;
|
||||
using Portable.Xaml.ComponentModel;
|
||||
using System.ComponentModel;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Avalonia.Controls;
|
||||
using Portable.Xaml.Schema;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.PortableXaml
|
||||
{
|
||||
class AvaloniaXamlObjectWriter : XamlObjectWriter
|
||||
{
|
||||
private static Dictionary<XamlDirective, string> DesignDirectives = new Dictionary<string, string>
|
||||
{
|
||||
["DataContext"] = "DataContext",
|
||||
["DesignWidth"] = "Width", ["DesignHeight"] = "Height", ["PreviewWith"] = "PreviewWith"
|
||||
}
|
||||
.ToDictionary(p => new XamlDirective(
|
||||
new[] {"http://schemas.microsoft.com/expression/blend/2008"}, p.Key,
|
||||
XamlLanguage.Object, null, AllowedMemberLocations.Attribute), p => p.Value);
|
||||
|
||||
private readonly AvaloniaXamlSchemaContext _schemaContext;
|
||||
|
||||
public static AvaloniaXamlObjectWriter Create(
|
||||
AvaloniaXamlSchemaContext schemaContext,
|
||||
AvaloniaXamlContext context,
|
||||
IAmbientProvider parentAmbientProvider = null)
|
||||
{
|
||||
var nameScope = new AvaloniaNameScope { Instance = context?.RootInstance };
|
||||
|
||||
var writerSettings = new XamlObjectWriterSettings()
|
||||
{
|
||||
ExternalNameScope = nameScope,
|
||||
RegisterNamesOnExternalNamescope = true,
|
||||
RootObjectInstance = context?.RootInstance
|
||||
};
|
||||
|
||||
return new AvaloniaXamlObjectWriter(schemaContext,
|
||||
writerSettings.WithContext(context),
|
||||
nameScope,
|
||||
parentAmbientProvider);
|
||||
}
|
||||
|
||||
private readonly DelayedValuesHelper _delayedValuesHelper = new DelayedValuesHelper();
|
||||
|
||||
private AvaloniaNameScope _nameScope;
|
||||
|
||||
private AvaloniaXamlObjectWriter(
|
||||
AvaloniaXamlSchemaContext schemaContext,
|
||||
XamlObjectWriterSettings settings,
|
||||
AvaloniaNameScope nameScope,
|
||||
IAmbientProvider parentAmbientProvider)
|
||||
: base(schemaContext, settings, parentAmbientProvider)
|
||||
{
|
||||
_nameScope = nameScope;
|
||||
_schemaContext = schemaContext;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (_nameScope != null && Result != null)
|
||||
{
|
||||
_nameScope.RegisterOnNameScope(Result);
|
||||
}
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
public void ApplyAllDelayedProperties()
|
||||
{
|
||||
//HACK: We need this because Begin/EndInit ordering is broken
|
||||
_delayedValuesHelper.ApplyAll();
|
||||
}
|
||||
|
||||
protected internal override void OnAfterProperties(object value)
|
||||
{
|
||||
_delayedValuesHelper.EndInit(value);
|
||||
|
||||
base.OnAfterProperties(value);
|
||||
}
|
||||
|
||||
protected internal override void OnBeforeProperties(object value)
|
||||
{
|
||||
if (value != null)
|
||||
_delayedValuesHelper.BeginInit(value);
|
||||
|
||||
base.OnBeforeProperties(value);
|
||||
}
|
||||
|
||||
protected internal override bool OnSetValue(object target, XamlMember member, object value)
|
||||
{
|
||||
if (_delayedValuesHelper.TryAdd(target, member, value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnSetValue(target, member, value);
|
||||
}
|
||||
|
||||
public override void WriteStartMember(XamlMember property)
|
||||
{
|
||||
foreach(var d in DesignDirectives)
|
||||
if (property == d.Key && _schemaContext.IsDesignMode)
|
||||
{
|
||||
base.WriteStartMember(new XamlMember(d.Value,
|
||||
typeof(Design).GetMethod("Get" + d.Value, BindingFlags.Static | BindingFlags.Public),
|
||||
typeof(Design).GetMethod("Set" + d.Value, BindingFlags.Static | BindingFlags.Public),
|
||||
SchemaContext));
|
||||
return;
|
||||
}
|
||||
base.WriteStartMember(property);
|
||||
}
|
||||
|
||||
private class DelayedValuesHelper
|
||||
{
|
||||
private int _cnt;
|
||||
|
||||
private HashSet<object> _targets = new HashSet<object>();
|
||||
|
||||
private IList<DelayedValue> _values = new List<DelayedValue>();
|
||||
|
||||
private IEnumerable<DelayedValue> Values => _values;
|
||||
|
||||
public void BeginInit(object target)
|
||||
{
|
||||
++_cnt;
|
||||
|
||||
AddTargetIfNeeded(target);
|
||||
}
|
||||
|
||||
public void EndInit(object target)
|
||||
{
|
||||
--_cnt;
|
||||
|
||||
if (_cnt == 0)
|
||||
{
|
||||
ApplyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryAdd(object target, XamlMember member, object value)
|
||||
{
|
||||
if (value is IBinding)
|
||||
{
|
||||
Add(new DelayedValue(target, member, value));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void Add(DelayedValue value)
|
||||
{
|
||||
_values.Add(value);
|
||||
|
||||
var target = value.Target;
|
||||
|
||||
if (!_targets.Contains(value.Target))
|
||||
{
|
||||
_targets.Add(target);
|
||||
(target as ISupportInitialize)?.BeginInit();
|
||||
}
|
||||
}
|
||||
|
||||
private void AddTargetIfNeeded(object target)
|
||||
{
|
||||
if (!_targets.Contains(target))
|
||||
{
|
||||
Add(new DelayedValue(target, null, null));
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyAll()
|
||||
{
|
||||
//TODO: revisit this
|
||||
//apply delayed values and clear
|
||||
//that's the last object let's set all delayed bindings
|
||||
foreach (var dv in Values.Where(v => v.Member != null))
|
||||
{
|
||||
dv.Member.Invoker.SetValue(dv.Target, dv.Value);
|
||||
}
|
||||
|
||||
//TODO: check/add some order of end init
|
||||
//currently we are sending end init in the order of
|
||||
//objects creation
|
||||
foreach (var v in Values)
|
||||
{
|
||||
var target = v.Target;
|
||||
|
||||
if (_targets.Contains(target))
|
||||
{
|
||||
_targets.Remove(target);
|
||||
(target as ISupportInitialize)?.EndInit();
|
||||
}
|
||||
}
|
||||
|
||||
_targets.Clear();
|
||||
_values.Clear();
|
||||
}
|
||||
|
||||
private class DelayedValue
|
||||
{
|
||||
public DelayedValue(object target, XamlMember member, object value)
|
||||
{
|
||||
Target = target;
|
||||
Member = member;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public XamlMember Member { get; }
|
||||
public object Target { get; }
|
||||
public object Value { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,327 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Markup.Xaml.Context;
|
||||
using Avalonia.Markup.Xaml.MarkupExtensions;
|
||||
using Avalonia.Markup.Xaml.Styling;
|
||||
using Portable.Xaml;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.PortableXaml
|
||||
{
|
||||
internal class AvaloniaXamlSchemaContext : XamlSchemaContext
|
||||
{
|
||||
private static AvaloniaXamlSchemaContext s_instance;
|
||||
private static AvaloniaXamlSchemaContext s_designInstance;
|
||||
|
||||
public static AvaloniaXamlSchemaContext Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_instance == null)
|
||||
{
|
||||
s_instance = Create();
|
||||
}
|
||||
|
||||
return s_instance;
|
||||
}
|
||||
}
|
||||
|
||||
public static AvaloniaXamlSchemaContext DesignInstance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_designInstance == null)
|
||||
{
|
||||
s_designInstance = Create();
|
||||
s_designInstance.IsDesignMode = true;
|
||||
}
|
||||
|
||||
return s_designInstance;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDesignMode { get; private set; }
|
||||
public static AvaloniaXamlSchemaContext Create(IRuntimeTypeProvider typeProvider = null)
|
||||
{
|
||||
return new AvaloniaXamlSchemaContext(typeProvider ?? new AvaloniaRuntimeTypeProvider());
|
||||
}
|
||||
|
||||
private AvaloniaXamlSchemaContext(IRuntimeTypeProvider typeProvider)
|
||||
//better not set the references assemblies
|
||||
//TODO: check this on iOS
|
||||
//: base(typeProvider.ReferencedAssemblies)
|
||||
{
|
||||
Contract.Requires<ArgumentNullException>(typeProvider != null);
|
||||
|
||||
_avaloniaTypeProvider = typeProvider;
|
||||
}
|
||||
|
||||
private IRuntimeTypeProvider _avaloniaTypeProvider;
|
||||
|
||||
protected override XamlType GetXamlType(string xamlNamespace, string name, params XamlType[] typeArguments)
|
||||
{
|
||||
XamlType type = null;
|
||||
try
|
||||
{
|
||||
type = ResolveXamlTypeName(xamlNamespace, name, typeArguments, false);
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
type = base.GetXamlType(xamlNamespace, name, typeArguments);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//TODO: log or wrap exception
|
||||
throw e;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private XamlType ResolveXamlTypeName(string xmlNamespace, string xmlLocalName, XamlType[] typeArguments, bool required)
|
||||
{
|
||||
Type[] genArgs = null;
|
||||
if (typeArguments != null && typeArguments.Any())
|
||||
{
|
||||
genArgs = typeArguments.Select(t => t?.UnderlyingType).ToArray();
|
||||
|
||||
if (genArgs.Any(t => t == null))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
Type extType;
|
||||
if (_wellKnownExtensionTypes.TryGetValue(type, out extType))
|
||||
{
|
||||
type = extType;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
//let's try the simple types
|
||||
//in Portable xaml like xmlns:sys='clr-namespace:System;assembly=mscorlib'
|
||||
//and sys:Double is not resolved properly
|
||||
return ResolveSimpleTypeName(xmlNamespace, xmlLocalName);
|
||||
}
|
||||
|
||||
return GetXamlType(type);
|
||||
}
|
||||
|
||||
#region Workaround for bug in Portablexaml system types like double,int etc ...
|
||||
|
||||
private static Type[] _simpleTypes = new Type[]
|
||||
{
|
||||
typeof(bool),
|
||||
typeof(byte),
|
||||
typeof(char),
|
||||
typeof(decimal),
|
||||
typeof(double),
|
||||
typeof(Int16),
|
||||
typeof(Int32),
|
||||
typeof(Int64),
|
||||
typeof(float),
|
||||
typeof(string),
|
||||
typeof(TimeSpan),
|
||||
typeof(Uri),
|
||||
};
|
||||
|
||||
private static Dictionary<Tuple<string, string>, XamlType> _simpleXamlTypes;
|
||||
|
||||
//in Portable xaml like xmlns:sys='clr-namespace:System;assembly=mscorlib'
|
||||
//and sys:Double is not resolved properly
|
||||
[Obsolete("TODO: remove once it's fixed in Portable.xaml")]
|
||||
private static XamlType ResolveSimpleTypeName(string xmlNamespace, string xmlLocalName)
|
||||
{
|
||||
if (_simpleXamlTypes == null)
|
||||
{
|
||||
_simpleXamlTypes = new Dictionary<Tuple<string, string>, XamlType>();
|
||||
|
||||
foreach (var type in _simpleTypes)
|
||||
{
|
||||
string asmName = type.GetTypeInfo().Assembly.GetName().Name;
|
||||
string ns = $"clr-namespace:{type.Namespace};assembly={asmName}";
|
||||
var xamlType = XamlLanguage.AllTypes.First(t => t.UnderlyingType == type);
|
||||
_simpleXamlTypes.Add(new Tuple<string, string>(ns, type.Name), xamlType);
|
||||
}
|
||||
}
|
||||
|
||||
XamlType result;
|
||||
|
||||
var key = new Tuple<string, string>(xmlNamespace, xmlLocalName);
|
||||
|
||||
_simpleXamlTypes.TryGetValue(key, out result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion Workaround for bug in Portablexaml system types like double,int etc ...
|
||||
|
||||
protected internal override ICustomAttributeProvider GetCustomAttributeProvider(Type type)
|
||||
=> new AvaloniaTypeAttributeProvider(type);
|
||||
|
||||
protected internal override ICustomAttributeProvider GetCustomAttributeProvider(MemberInfo member)
|
||||
=> new AvaloniaMemberAttributeProvider(member);
|
||||
|
||||
public override XamlType GetXamlType(Type type)
|
||||
{
|
||||
XamlType result = null;
|
||||
|
||||
if (_cachedTypes.TryGetValue(type, out result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
_cachedTypes[type] = result = GetAvaloniaXamlType(type) ?? base.GetXamlType(type);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static readonly Dictionary<Type, Type> _wellKnownExtensionTypes = new Dictionary<Type, Type>()
|
||||
{
|
||||
{ typeof(Binding), typeof(BindingExtension) },
|
||||
{ typeof(StyleInclude), typeof(StyleIncludeExtension) },
|
||||
};
|
||||
|
||||
private XamlType GetAvaloniaXamlType(Type type)
|
||||
{
|
||||
//if type is extension get the original type to check
|
||||
var origType = _wellKnownExtensionTypes.FirstOrDefault(v => v.Value == type).Key;
|
||||
|
||||
if (typeof(IBinding).GetTypeInfo().IsAssignableFrom((origType ?? type).GetTypeInfo()))
|
||||
{
|
||||
return new BindingXamlType(type, this);
|
||||
}
|
||||
|
||||
if (origType != null ||
|
||||
typeof(AvaloniaObject).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()))
|
||||
{
|
||||
return new AvaloniaXamlType(type, this);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected internal override XamlMember GetAttachableProperty(string attachablePropertyName, MethodInfo getter, MethodInfo setter)
|
||||
{
|
||||
var key = MemberKey.Create(getter ?? setter, attachablePropertyName, "a");
|
||||
|
||||
XamlMember result;
|
||||
|
||||
if (_cachedMembers.TryGetValue(key, out result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
var type = (getter ?? setter).DeclaringType;
|
||||
|
||||
var prop = AvaloniaPropertyRegistry.Instance.FindRegistered(type, attachablePropertyName);
|
||||
|
||||
if (prop != null)
|
||||
{
|
||||
result = new AvaloniaAttachedPropertyXamlMember(
|
||||
prop, attachablePropertyName,
|
||||
getter, setter, this);
|
||||
}
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
result = base.GetAttachableProperty(attachablePropertyName, getter, setter);
|
||||
}
|
||||
|
||||
return _cachedMembers[key] = result;
|
||||
}
|
||||
|
||||
protected internal override XamlMember GetProperty(PropertyInfo pi)
|
||||
{
|
||||
Type objType = pi.DeclaringType;
|
||||
string name = pi.Name;
|
||||
|
||||
XamlMember result;
|
||||
|
||||
var key = MemberKey.Create(pi, "p");
|
||||
|
||||
if (_cachedMembers.TryGetValue(key, out result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
var avProp = AvaloniaPropertyRegistry.Instance.FindRegistered(objType, name);
|
||||
|
||||
if (avProp != null)
|
||||
{
|
||||
result = new AvaloniaPropertyXamlMember(avProp, pi, this);
|
||||
}
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
result = new PropertyXamlMember(pi, this);
|
||||
}
|
||||
|
||||
return _cachedMembers[key] = result;
|
||||
}
|
||||
|
||||
private Dictionary<Type, XamlType> _cachedTypes = new Dictionary<Type, XamlType>();
|
||||
|
||||
private Dictionary<MemberKey, XamlMember> _cachedMembers = new Dictionary<MemberKey, XamlMember>();
|
||||
|
||||
private struct MemberKey
|
||||
{
|
||||
public static MemberKey Create(MemberInfo m, string name, string memberType)
|
||||
{
|
||||
return new MemberKey(m.DeclaringType, name, memberType);
|
||||
}
|
||||
|
||||
public static MemberKey Create(MemberInfo m, string memberType)
|
||||
{
|
||||
return Create(m, m.Name, memberType);
|
||||
}
|
||||
|
||||
public MemberKey(Type type, object member, string memberType)
|
||||
{
|
||||
Type = type;
|
||||
Member = member;
|
||||
MemberType = memberType;
|
||||
}
|
||||
|
||||
public Type Type { get; }
|
||||
|
||||
public object Member { get; }
|
||||
|
||||
public string MemberType { get; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{MemberType}:{Type.Namespace}:{Type.Name}.{Member}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override bool TryGetCompatibleXamlNamespace(string xamlNamespace, out string compatibleNamespace)
|
||||
{
|
||||
//Forces XamlXmlReader to not ignore our namespace in design mode if mc:Ignorable is set
|
||||
if (IsDesignMode &&
|
||||
xamlNamespace == "http://schemas.microsoft.com/expression/blend/2008")
|
||||
{
|
||||
compatibleNamespace = xamlNamespace;
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.TryGetCompatibleXamlNamespace(xamlNamespace, out compatibleNamespace);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,388 +0,0 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Markup.Data;
|
||||
using Avalonia.Metadata;
|
||||
using Avalonia.Styling;
|
||||
using Portable.Xaml;
|
||||
using Portable.Xaml.Schema;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.PortableXaml
|
||||
{
|
||||
using Converters;
|
||||
using PropertyKey = Tuple<Type, string>;
|
||||
|
||||
public class AvaloniaXamlType : XamlType
|
||||
{
|
||||
static readonly AvaloniaPropertyTypeConverter propertyTypeConverter = new AvaloniaPropertyTypeConverter();
|
||||
|
||||
public AvaloniaXamlType(Type underlyingType, XamlSchemaContext schemaContext) :
|
||||
base(underlyingType, schemaContext)
|
||||
{
|
||||
}
|
||||
|
||||
protected override XamlMember LookupAttachableMember(string name)
|
||||
{
|
||||
var m = base.LookupAttachableMember(name);
|
||||
|
||||
if (m == null)
|
||||
{
|
||||
// Might be an AddOwnered attached property.
|
||||
var avProp = AvaloniaPropertyRegistry.Instance.FindRegistered(UnderlyingType, name);
|
||||
|
||||
if (avProp?.IsAttached == true)
|
||||
{
|
||||
return new AvaloniaPropertyXamlMember(avProp, this);
|
||||
}
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
protected override XamlMember LookupMember(string name, bool skipReadOnlyCheck)
|
||||
{
|
||||
var m = base.LookupMember(name, skipReadOnlyCheck);
|
||||
|
||||
if (m == null && !name.Contains("."))
|
||||
{
|
||||
//so far Portable.xaml haven't found the member/property
|
||||
//but what if we have AvaloniaProperty
|
||||
//without setter and/or without getter
|
||||
//let's try to find the AvaloniaProperty as a fallback
|
||||
var avProp = AvaloniaPropertyRegistry.Instance.FindRegistered(UnderlyingType, name);
|
||||
|
||||
if (avProp != null && !(skipReadOnlyCheck && avProp.IsReadOnly))
|
||||
{
|
||||
m = new AvaloniaPropertyXamlMember(avProp, this);
|
||||
}
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
||||
public class BindingXamlType : XamlType
|
||||
{
|
||||
private static List<Type> _notAssignable =
|
||||
new List<Type>
|
||||
{
|
||||
typeof (IXmlSerializable)
|
||||
};
|
||||
|
||||
public BindingXamlType(Type underlyingType, XamlSchemaContext schemaContext) :
|
||||
base(underlyingType, schemaContext)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanAssignTo(XamlType xamlType)
|
||||
{
|
||||
return !_notAssignable.Contains(xamlType.UnderlyingType);
|
||||
}
|
||||
}
|
||||
|
||||
public class PropertyXamlMember : XamlMember
|
||||
{
|
||||
public PropertyXamlMember(PropertyInfo propertyInfo, XamlSchemaContext schemaContext)
|
||||
: base(propertyInfo, schemaContext)
|
||||
{
|
||||
}
|
||||
|
||||
protected PropertyXamlMember(string attachablePropertyName,
|
||||
MethodInfo getter, MethodInfo setter, XamlSchemaContext schemaContext)
|
||||
: base(attachablePropertyName, getter, setter, schemaContext)
|
||||
{
|
||||
}
|
||||
|
||||
protected PropertyXamlMember(string name, XamlType declaringType, bool isAttachable)
|
||||
: base(name, declaringType, isAttachable)
|
||||
{
|
||||
}
|
||||
|
||||
private bool IsReadOnlyCollectionProperty
|
||||
{
|
||||
get
|
||||
{
|
||||
//Collection properties like:
|
||||
//MultiBinding.Bindings, Panel.Children, Control.Styles,
|
||||
//need to be readonly for Portable.Xaml
|
||||
//Collection properties like:
|
||||
//Grid.RowDefinitions, Grid.ColumnDefinitions
|
||||
//need to be set only once, and subsequent changes to be
|
||||
//added to collection
|
||||
//TODO: investigate is this good enough as solution ???
|
||||
//We can add some ReadOnyXamlPropertyCollectionAttribute to cover this
|
||||
return Type.IsCollection;
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasCollectionTypeConverter
|
||||
{
|
||||
get
|
||||
{
|
||||
return Type.IsCollection && Type.TypeConverter != null;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
if (IsReadOnlyCollectionProperty &&
|
||||
!HasCollectionTypeConverter)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return base.LookupUnderlyingSetter();
|
||||
}
|
||||
|
||||
protected override XamlMemberInvoker LookupInvoker()
|
||||
{
|
||||
//if we have a IList property and it has TypeConverter
|
||||
//Portable.xaml need to be able to set the value
|
||||
//but instead directly set new value we'll sync the lists
|
||||
bool updateListInsteadSet = HasCollectionTypeConverter;
|
||||
return new PropertyInvoker(this)
|
||||
{
|
||||
UpdateListInsteadSet = updateListInsteadSet
|
||||
};
|
||||
}
|
||||
|
||||
protected override bool LookupIsUnknown() => false;
|
||||
|
||||
protected override XamlType LookupType()
|
||||
{
|
||||
var propType = GetPropertyType();
|
||||
|
||||
if (propType != null)
|
||||
{
|
||||
if (propType == typeof(IEnumerable))
|
||||
{
|
||||
//TODO: Portable.xaml is not handling well IEnumerable
|
||||
//let's threat IEnumerable property as list
|
||||
//revisit this when smarter solution is found
|
||||
propType = typeof(IList);
|
||||
}
|
||||
|
||||
return DeclaringType.SchemaContext.GetXamlType(propType);
|
||||
}
|
||||
|
||||
return base.LookupType();
|
||||
}
|
||||
|
||||
protected virtual Type GetPropertyType()
|
||||
{
|
||||
return (UnderlyingMember as PropertyInfo)?.PropertyType;
|
||||
}
|
||||
|
||||
private IList<XamlMember> _dependsOn;
|
||||
|
||||
protected override IList<XamlMember> LookupDependsOn()
|
||||
{
|
||||
if (_dependsOn == null)
|
||||
{
|
||||
var attrib = UnderlyingMember.GetCustomAttribute<DependsOnAttribute>(true);
|
||||
|
||||
if (attrib != null)
|
||||
{
|
||||
var member = DeclaringType.GetMember(attrib.Name);
|
||||
|
||||
_dependsOn = new XamlMember[] { member };
|
||||
}
|
||||
else
|
||||
{
|
||||
_dependsOn = base.LookupDependsOn();
|
||||
}
|
||||
}
|
||||
|
||||
return _dependsOn;
|
||||
}
|
||||
|
||||
private PropertyKey PropertyKey()
|
||||
=> new PropertyKey(DeclaringType.UnderlyingType, Name);
|
||||
|
||||
private class PropertyInvoker : XamlMemberInvoker
|
||||
{
|
||||
public bool UpdateListInsteadSet { get; set; } = false;
|
||||
|
||||
public PropertyInvoker(XamlMember member) : base(member)
|
||||
{
|
||||
}
|
||||
|
||||
public override void SetValue(object instance, object value)
|
||||
{
|
||||
//can't make it work to assign TypeConverter to Setter.Value
|
||||
//so we need it hard coded
|
||||
//TODO: try to assosiate TypeConverter with Setter.Value
|
||||
//and remove this lines
|
||||
if (instance is Setter &&
|
||||
Member.Name == nameof(Setter.Value) &&
|
||||
value is string)
|
||||
{
|
||||
value = SetterValueTypeConverter.ConvertSetterValue(null,
|
||||
Member.DeclaringType.SchemaContext, CultureInfo.InvariantCulture,
|
||||
instance as Setter,
|
||||
value);
|
||||
}
|
||||
|
||||
if (UpdateListInsteadSet &&
|
||||
value != null &&
|
||||
UpdateListInsteadSetValue(instance, value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
base.SetValue(instance, value);
|
||||
}
|
||||
|
||||
private bool UpdateListInsteadSetValue(object instance, object value)
|
||||
{
|
||||
object old = GetValue(instance);
|
||||
|
||||
if (Equals(old, value))
|
||||
{
|
||||
//don't set the same collection value
|
||||
return true;
|
||||
}
|
||||
else if (old is IList && value is IList)
|
||||
{
|
||||
var oldList = (IList)old;
|
||||
var curList = (IList)value;
|
||||
|
||||
oldList.Clear();
|
||||
|
||||
foreach (object item in curList)
|
||||
{
|
||||
oldList.Add(item);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class AvaloniaPropertyXamlMember : PropertyXamlMember
|
||||
{
|
||||
private bool? _assignBinding;
|
||||
|
||||
public bool AssignBinding => (bool)(_assignBinding ?? (_assignBinding = UnderlyingMember?.GetCustomAttribute<AssignBindingAttribute>() != null));
|
||||
|
||||
public AvaloniaProperty Property { get; }
|
||||
|
||||
public AvaloniaPropertyXamlMember(AvaloniaProperty property,
|
||||
PropertyInfo propertyInfo,
|
||||
XamlSchemaContext schemaContext) :
|
||||
base(propertyInfo, schemaContext)
|
||||
{
|
||||
Property = property;
|
||||
}
|
||||
|
||||
public AvaloniaPropertyXamlMember(AvaloniaProperty property, XamlType type) :
|
||||
base(property.Name, type, false)
|
||||
{
|
||||
Property = property;
|
||||
}
|
||||
|
||||
protected AvaloniaPropertyXamlMember(AvaloniaProperty property,
|
||||
string attachablePropertyName,
|
||||
MethodInfo getter, MethodInfo setter, XamlSchemaContext schemaContext)
|
||||
: base(attachablePropertyName, getter, setter, schemaContext)
|
||||
{
|
||||
Property = property;
|
||||
}
|
||||
|
||||
protected override XamlMemberInvoker LookupInvoker()
|
||||
{
|
||||
return new AvaloniaPropertyInvoker(this);
|
||||
}
|
||||
|
||||
protected override bool LookupIsReadOnly()
|
||||
{
|
||||
return Property.IsReadOnly;
|
||||
}
|
||||
|
||||
protected override Type GetPropertyType()
|
||||
{
|
||||
return Property.PropertyType;
|
||||
}
|
||||
|
||||
private class AvaloniaPropertyInvoker : XamlMemberInvoker
|
||||
{
|
||||
public AvaloniaPropertyInvoker(XamlMember member) : base(member)
|
||||
{
|
||||
}
|
||||
|
||||
public override void SetValue(object instance, object value)
|
||||
{
|
||||
if (Property != null)
|
||||
{
|
||||
var obj = ((IAvaloniaObject)instance);
|
||||
if (value is IBinding)
|
||||
{
|
||||
if (!Member.AssignBinding)
|
||||
ApplyBinding(obj, (IBinding)value);
|
||||
else
|
||||
obj.SetValue(Property, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj.SetValue(Property, value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
base.SetValue(instance, value);
|
||||
}
|
||||
}
|
||||
|
||||
public override object GetValue(object instance)
|
||||
{
|
||||
if (Property != null && !Property.IsAttached)
|
||||
{
|
||||
return ((IAvaloniaObject)instance).GetValue(Property);
|
||||
}
|
||||
else
|
||||
{
|
||||
return base.GetValue(instance);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyBinding(IAvaloniaObject obj, IBinding binding)
|
||||
{
|
||||
var control = obj as IControl;
|
||||
var property = Property;
|
||||
|
||||
if (control != null && property != Control.DataContextProperty)
|
||||
DelayedBinding.Add(control, property, binding);
|
||||
else
|
||||
obj.Bind(property, binding);
|
||||
}
|
||||
|
||||
private AvaloniaProperty Property => Member.Property;
|
||||
|
||||
private new AvaloniaPropertyXamlMember Member =>
|
||||
(AvaloniaPropertyXamlMember)base.Member;
|
||||
}
|
||||
}
|
||||
|
||||
public class AvaloniaAttachedPropertyXamlMember : AvaloniaPropertyXamlMember
|
||||
{
|
||||
public AvaloniaAttachedPropertyXamlMember(AvaloniaProperty property,
|
||||
string attachablePropertyName,
|
||||
MethodInfo getter, MethodInfo setter,
|
||||
XamlSchemaContext schemaContext)
|
||||
: base(property, attachablePropertyName, getter, setter, schemaContext)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
using Avalonia.Markup.Xaml.PortableXaml;
|
||||
using Portable.Xaml.Markup;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.ComponentModel;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public static T GetFirstAmbientValue<T>(this ITypeDescriptorContext ctx) where T : class
|
||||
{
|
||||
var amb = ctx.GetService<IAmbientProvider>();
|
||||
var sc = ctx.GetService<IXamlSchemaContextProvider>().SchemaContext;
|
||||
|
||||
// Because GetFirstParent uses XamlType.CanAssignTo it returns values that
|
||||
// aren't actually of the correct type. Use GetAllAmbientValues instead.
|
||||
return amb.GetAllAmbientValues(sc.GetXamlType(typeof(T))).OfType<T>().FirstOrDefault();
|
||||
}
|
||||
|
||||
public static T GetLastOrDefaultAmbientValue<T>(this ITypeDescriptorContext ctx) where T : class
|
||||
{
|
||||
return ctx.GetAllAmbientValues<T>().LastOrDefault() as T;
|
||||
}
|
||||
|
||||
public static IEnumerable<T> GetAllAmbientValues<T>(this ITypeDescriptorContext ctx) where T : class
|
||||
{
|
||||
var amb = ctx.GetService<IAmbientProvider>();
|
||||
var sc = ctx.GetService<IXamlSchemaContextProvider>().SchemaContext;
|
||||
|
||||
return amb.GetAllAmbientValues(sc.GetXamlType(typeof(T))).OfType<T>();
|
||||
}
|
||||
|
||||
public static Uri GetBaseUri(this ITypeDescriptorContext ctx)
|
||||
{
|
||||
return ctx.GetWriterSettings()?.Context?.BaseUri;
|
||||
}
|
||||
|
||||
public static Assembly GetLocalAssembly(this ITypeDescriptorContext ctx)
|
||||
{
|
||||
return ctx.GetWriterSettings()?.Context?.LocalAssembly;
|
||||
}
|
||||
|
||||
public static AvaloniaXamlContext GetAvaloniaXamlContext(this ITypeDescriptorContext ctx)
|
||||
{
|
||||
return ctx.GetWriterSettings()?.Context;
|
||||
}
|
||||
|
||||
public static XamlObjectWriterSettings WithContext(this XamlObjectWriterSettings settings, AvaloniaXamlContext context)
|
||||
{
|
||||
return new AvaloniaXamlObjectWriterSettings(settings, context);
|
||||
}
|
||||
|
||||
private static AvaloniaXamlObjectWriterSettings GetWriterSettings(this ITypeDescriptorContext ctx)
|
||||
{
|
||||
return ctx.GetService<IXamlObjectWriterFactory>().GetParentSettings() as AvaloniaXamlObjectWriterSettings;
|
||||
}
|
||||
|
||||
private class AvaloniaXamlObjectWriterSettings : XamlObjectWriterSettings
|
||||
{
|
||||
public AvaloniaXamlObjectWriterSettings(XamlObjectWriterSettings settings, AvaloniaXamlContext context)
|
||||
: base(settings)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
public AvaloniaXamlContext Context { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
Submodule src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github deleted from ab55261737
@@ -7,42 +7,16 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.Templates
|
||||
{
|
||||
using Portable.Xaml;
|
||||
|
||||
public class TemplateContent
|
||||
|
||||
public static class TemplateContent
|
||||
{
|
||||
public TemplateContent(IEnumerable<NamespaceDeclaration> namespaces, XamlReader reader,
|
||||
IAmbientProvider ambientProvider)
|
||||
{
|
||||
ParentAmbientProvider = ambientProvider;
|
||||
List = new XamlNodeList(reader.SchemaContext);
|
||||
|
||||
//we need to rpeserve all namespace and prefixes to writer
|
||||
//otherwise they are lost. a bug in Portable.xaml or by design ??
|
||||
foreach (var ns in namespaces)
|
||||
{
|
||||
List.Writer.WriteNamespace(ns);
|
||||
}
|
||||
|
||||
XamlServices.Transform(reader, List.Writer);
|
||||
}
|
||||
|
||||
public XamlNodeList List { get; }
|
||||
|
||||
private IAmbientProvider ParentAmbientProvider { get; }
|
||||
|
||||
public IControl Load()
|
||||
{
|
||||
return (IControl)AvaloniaXamlLoader.LoadFromReader(List.GetReader(), parentAmbientProvider: ParentAmbientProvider);
|
||||
}
|
||||
|
||||
public static IControl Load(object templateContent)
|
||||
{
|
||||
if (templateContent is Func<IServiceProvider, object> direct)
|
||||
{
|
||||
return (IControl)direct(null);
|
||||
}
|
||||
return ((TemplateContent)templateContent).Load();
|
||||
throw new ArgumentException(nameof(templateContent));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
// 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.
|
||||
|
||||
namespace Avalonia.Markup.Xaml.Templates
|
||||
{
|
||||
using Portable.Xaml;
|
||||
using Portable.Xaml.ComponentModel;
|
||||
using System.ComponentModel;
|
||||
using System;
|
||||
|
||||
public class TemplateLoader : XamlDeferringLoader
|
||||
{
|
||||
public override object Load(XamlReader xamlReader, IServiceProvider serviceProvider)
|
||||
{
|
||||
var tdc = (ITypeDescriptorContext)serviceProvider;
|
||||
var ns = tdc.GetService<IXamlNamespaceResolver>();
|
||||
var ambientProvider = tdc.GetService<IAmbientProvider>();
|
||||
return new TemplateContent(ns.GetNamespacePrefixes(), xamlReader, ambientProvider);
|
||||
}
|
||||
|
||||
public override XamlReader Save(object value, IServiceProvider serviceProvider)
|
||||
{
|
||||
return ((TemplateContent)value).List.GetReader();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,15 +28,14 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
|
||||
XmlnsAttributes =
|
||||
{
|
||||
typeSystem.GetType("Avalonia.Metadata.XmlnsDefinitionAttribute"),
|
||||
typeSystem.FindType("Portable.Xaml.Markup.XmlnsDefinitionAttribute")
|
||||
},
|
||||
ContentAttributes =
|
||||
{
|
||||
typeSystem.GetType("Avalonia.Metadata.ContentAttribute")
|
||||
},
|
||||
ProvideValueTarget = typeSystem.GetType("Portable.Xaml.Markup.IProvideValueTarget"),
|
||||
RootObjectProvider = typeSystem.GetType("Portable.Xaml.IRootObjectProvider"),
|
||||
UriContextProvider = typeSystem.GetType("Portable.Xaml.Markup.IUriContext"),
|
||||
ProvideValueTarget = typeSystem.GetType("Avalonia.Markup.Xaml.IProvideValueTarget"),
|
||||
RootObjectProvider = typeSystem.GetType("Avalonia.Markup.Xaml.IRootObjectProvider"),
|
||||
UriContextProvider = typeSystem.GetType("Avalonia.Markup.Xaml.IUriContext"),
|
||||
ParentStackProvider =
|
||||
typeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.IAvaloniaXamlIlParentStackProvider"),
|
||||
|
||||
@@ -47,7 +46,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
|
||||
runtimeHelpers.FindMethod(m => m.Name == "DeferredTransformationFactoryV1"),
|
||||
UsableDuringInitializationAttributes =
|
||||
{
|
||||
typeSystem.GetType("Portable.Xaml.Markup.UsableDuringInitializationAttribute"),
|
||||
typeSystem.GetType("Avalonia.Metadata.UsableDuringInitializationAttribute"),
|
||||
},
|
||||
InnerServiceProviderFactoryMethod =
|
||||
@@ -79,15 +77,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
|
||||
void Add(string type, string conv)
|
||||
=> AddType(typeSystem.GetType(type), typeSystem.GetType(conv));
|
||||
|
||||
|
||||
//Add("Avalonia.AvaloniaProperty","Avalonia.Markup.Xaml.Converters.AvaloniaPropertyTypeConverter");
|
||||
Add("Avalonia.Media.Imaging.IBitmap","Avalonia.Markup.Xaml.Converters.BitmapTypeConverter");
|
||||
var ilist = typeSystem.GetType("System.Collections.Generic.IList`1");
|
||||
AddType(ilist.MakeGenericType(typeSystem.GetType("Avalonia.Point")),
|
||||
typeSystem.GetType("Avalonia.Markup.Xaml.Converters.PointsListTypeConverter"));
|
||||
Add("Avalonia.Controls.Templates.IMemberSelector",
|
||||
"Avalonia.Markup.Xaml.Converters.MemberSelectorTypeConverter");
|
||||
Add("Avalonia.Styling.Selector","Avalonia.Markup.Xaml.Converters.SelectorTypeConverter");
|
||||
Add("Avalonia.Controls.WindowIcon","Avalonia.Markup.Xaml.Converters.IconTypeConverter");
|
||||
Add("System.Globalization.CultureInfo", "System.ComponentModel.CultureInfoConverter");
|
||||
Add("System.Uri", "Avalonia.Markup.Xaml.Converters.AvaloniaUriTypeConverter");
|
||||
|
||||
@@ -4,8 +4,6 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Data;
|
||||
using Portable.Xaml;
|
||||
using Portable.Xaml.Markup;
|
||||
// ReSharper disable UnusedMember.Global
|
||||
// ReSharper disable UnusedParameter.Global
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
|
||||
namespace Avalonia.Markup.Xaml
|
||||
{
|
||||
public interface IProvideValueTarget
|
||||
{
|
||||
object TargetObject { get; }
|
||||
object TargetProperty { get; }
|
||||
}
|
||||
|
||||
public interface IRootObjectProvider
|
||||
{
|
||||
object RootObject { get; }
|
||||
}
|
||||
|
||||
public interface IUriContext
|
||||
{
|
||||
Uri BaseUri { get; set; }
|
||||
}
|
||||
|
||||
public interface IXamlTypeResolver
|
||||
{
|
||||
Type Resolve (string qualifiedTypeName);
|
||||
}
|
||||
|
||||
|
||||
public class ConstructorArgumentAttribute : Attribute
|
||||
{
|
||||
public ConstructorArgumentAttribute(string name)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
<Application xmlns="https://github.com/avaloniaui">
|
||||
<Application xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="Avalonia.DesignerSupport.TestApp.App">
|
||||
<Application.Styles>
|
||||
<StyleInclude Source="resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default"/>
|
||||
<StyleInclude Source="resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"/>
|
||||
</Application.Styles>
|
||||
</Application>
|
||||
</Application>
|
||||
|
||||
@@ -31,6 +31,6 @@
|
||||
<ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
|
||||
<ProjectReference Include="..\..\src\Avalonia.Desktop\Avalonia.Desktop.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\..\build\BuildTargets.targets" />
|
||||
<Import Project="..\..\build\Serilog.props" />
|
||||
</Project>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:pages="clr-namespace:ControlCatalog.Pages;assembly=ControlCatalog"
|
||||
Title="TESTAPP">
|
||||
Title="TESTAPP"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="Avalonia.DesignerSupport.TestApp.MainWindow">
|
||||
<Button/>
|
||||
</Window>
|
||||
</Window>
|
||||
|
||||
@@ -118,10 +118,21 @@ namespace Avalonia.DesignerSupport.Tests
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
Assert.True(cancelled, $"Message Not Received.");
|
||||
Assert.NotEqual(0, handle);
|
||||
proc.Kill();
|
||||
try
|
||||
{
|
||||
proc.Kill();
|
||||
}
|
||||
catch
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
proc.WaitForExit();
|
||||
Assert.True(cancelled,
|
||||
$"Message Not Received.\n" + proc.StandardOutput.ReadToEnd() + "\n" +
|
||||
proc.StandardError.ReadToEnd());
|
||||
Assert.NotEqual(0, handle);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,7 @@ using Avalonia.Markup.Xaml.Converters;
|
||||
using Avalonia.Styling;
|
||||
using Xunit;
|
||||
using System.ComponentModel;
|
||||
using Portable.Xaml;
|
||||
using Portable.Xaml.Markup;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml.XamlIl.Runtime;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.UnitTests.Converters
|
||||
{
|
||||
@@ -91,27 +89,23 @@ namespace Avalonia.Markup.Xaml.UnitTests.Converters
|
||||
Assert.Equal("Could not find property 'AttachedOwner.NonExistent'.", ex.Message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private ITypeDescriptorContext CreateContext(Style style = null)
|
||||
{
|
||||
var tdMock = new Mock<ITypeDescriptorContext>();
|
||||
var xsc = new Mock<IXamlSchemaContextProvider>();
|
||||
var sc = Mock.Of<XamlSchemaContext>();
|
||||
var amb = new Mock<IAmbientProvider>();
|
||||
var tr = new Mock<IXamlTypeResolver>();
|
||||
var ps = new Mock<IAvaloniaXamlIlParentStackProvider>();
|
||||
|
||||
tdMock.Setup(d => d.GetService(typeof(IAmbientProvider)))
|
||||
.Returns(amb.Object);
|
||||
tdMock.Setup(d => d.GetService(typeof(IXamlSchemaContextProvider)))
|
||||
.Returns(xsc.Object);
|
||||
tdMock.Setup(d => d.GetService(typeof(IXamlTypeResolver)))
|
||||
.Returns(tr.Object);
|
||||
|
||||
xsc.SetupGet(v => v.SchemaContext)
|
||||
.Returns(sc);
|
||||
amb.Setup(v => v.GetFirstAmbientValue(It.IsAny<Portable.Xaml.XamlType>()))
|
||||
.Returns(style);
|
||||
amb.Setup(v => v.GetAllAmbientValues(It.IsAny<Portable.Xaml.XamlType>()))
|
||||
.Returns(new object[] { style });
|
||||
tdMock.Setup(d => d.GetService(typeof(IAvaloniaXamlIlParentStackProvider)))
|
||||
.Returns(ps.Object);
|
||||
|
||||
ps.SetupGet(v => v.Parents)
|
||||
.Returns(new object[] {style});
|
||||
|
||||
tr.Setup(v => v.Resolve(nameof(Class1)))
|
||||
.Returns(typeof(Class1));
|
||||
tr.Setup(v => v.Resolve(nameof(AttachedOwner)))
|
||||
|
||||
@@ -14,7 +14,6 @@ using Avalonia.Media;
|
||||
using Avalonia.Media.Immutable;
|
||||
using Avalonia.Styling;
|
||||
using Avalonia.UnitTests;
|
||||
using Portable.Xaml;
|
||||
using System.Collections;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
@@ -47,37 +46,6 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
|
||||
Assert.Equal("Foo", target.Content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AvaloniaProperty_Without_Getter_And_Setter_Is_Set()
|
||||
{
|
||||
// It's not possible to know in compile time if a read-only property has a magic way of being not read-only
|
||||
if (!AvaloniaXamlLoader.UseLegacyXamlLoader)
|
||||
return;
|
||||
var xaml =
|
||||
@"<local:NonControl xmlns='https://github.com/avaloniaui'
|
||||
xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'
|
||||
Foo='55' />";
|
||||
|
||||
var target = AvaloniaXamlLoader.Parse<NonControl>(xaml);
|
||||
|
||||
Assert.Equal(55, target.GetValue(NonControl.FooProperty));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AvaloniaProperty_With_Getter_And_No_Setter_Is_Set()
|
||||
{
|
||||
if(!AvaloniaXamlLoader.UseLegacyXamlLoader)
|
||||
return;
|
||||
var xaml =
|
||||
@"<local:NonControl xmlns='https://github.com/avaloniaui'
|
||||
xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'
|
||||
Bar='bar' />";
|
||||
|
||||
var target = AvaloniaXamlLoader.Parse<NonControl>(xaml);
|
||||
|
||||
Assert.Equal("bar", target.Bar);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Attached_Property_Is_Set()
|
||||
{
|
||||
@@ -159,19 +127,6 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
|
||||
XamlTestHelpers.AssertThrowsXamlException(() => AvaloniaXamlLoader.Parse<ContentControl>(xaml));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Non_Attached_Property_With_Attached_Property_Syntax_Throws()
|
||||
{
|
||||
// 1) It has been allowed in AvaloniaObject.SetValue for ages
|
||||
// 2) There is no way to know if AddOwner was called in compile-time
|
||||
if (!AvaloniaXamlLoader.UseLegacyXamlLoader)
|
||||
return;
|
||||
var xaml =
|
||||
@"<ContentControl xmlns='https://github.com/avaloniaui' TextBlock.Text='foo'/>";
|
||||
|
||||
XamlTestHelpers.AssertThrowsXamlException(() => AvaloniaXamlLoader.Parse<ContentControl>(xaml));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContentControl_ContentTemplate_Is_Functional()
|
||||
{
|
||||
@@ -595,31 +550,6 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Xaml_Binding_Is_Delayed()
|
||||
{
|
||||
if (!AvaloniaXamlLoader.UseLegacyXamlLoader)
|
||||
return;
|
||||
|
||||
using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
|
||||
{
|
||||
var xaml =
|
||||
@"<ContentControl xmlns='https://github.com/avaloniaui' Content='{Binding}'/>";
|
||||
|
||||
var target = AvaloniaXamlLoader.Parse<ContentControl>(xaml);
|
||||
|
||||
Assert.Null(target.Content);
|
||||
|
||||
target.DataContext = "Foo";
|
||||
|
||||
Assert.Null(target.Content);
|
||||
|
||||
DelayedBinding.ApplyBindings(target);
|
||||
|
||||
Assert.Equal("Foo", target.Content);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Double_Xaml_Binding_Is_Operational()
|
||||
{
|
||||
|
||||
@@ -5,7 +5,6 @@ using System;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Portable.Xaml;
|
||||
using Xunit;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.UnitTests.Xaml
|
||||
@@ -35,19 +34,6 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
|
||||
XamlTestHelpers.AssertThrowsXamlException(() => loader.Load(xaml, rootInstance: target));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Exception_Is_Not_Thrown_If_Event_Not_Found_In_Design_Mode()
|
||||
{
|
||||
// Runtime compiler should properly understand x:Class
|
||||
if (!AvaloniaXamlLoader.UseLegacyXamlLoader)
|
||||
return;
|
||||
var xaml = @"<Button xmlns='https://github.com/avaloniaui' Click='NotFound'/>";
|
||||
var loader = new AvaloniaXamlLoader { IsDesignMode = true };
|
||||
var target = new MyButton();
|
||||
|
||||
loader.Load(xaml, rootInstance: target);
|
||||
}
|
||||
|
||||
private void RaiseClick(MyButton target)
|
||||
{
|
||||
target.RaiseEvent(new KeyEventArgs
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// 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.Xml;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Data;
|
||||
using Avalonia.Markup.Xaml.Styling;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Styling;
|
||||
using Avalonia.UnitTests;
|
||||
using Portable.Xaml;
|
||||
using Xunit;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.UnitTests.Xaml
|
||||
@@ -191,7 +191,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
|
||||
<TextBlock/>
|
||||
</Window>";
|
||||
var loader = new AvaloniaXamlLoader();
|
||||
var ex = Assert.Throws<XamlObjectWriterException>(() => loader.Load(xaml));
|
||||
var ex = Assert.Throws<XmlException>(() => loader.Load(xaml));
|
||||
|
||||
Assert.Equal(
|
||||
"Property 'Button.IsDefault' is not registered on 'Avalonia.Controls.TextBlock'.",
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Xml;
|
||||
using Portable.Xaml;
|
||||
|
||||
namespace Avalonia.Markup.Xaml.UnitTests.Xaml
|
||||
{
|
||||
@@ -14,7 +13,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if(e is XamlObjectWriterException || e is XmlException)
|
||||
if(e is XmlException)
|
||||
return;
|
||||
}
|
||||
throw new Exception("Expected to throw xaml exception");
|
||||
|
||||
Reference in New Issue
Block a user