diff --git a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs index ec668f2a2b..df840464c1 100644 --- a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs +++ b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs @@ -150,7 +150,8 @@ namespace Avalonia.Build.Tasks classType = typeSystem.TargetAssembly.FindType(tn.Text); if (classType == null) throw new XamlIlParseException($"Unable to find type `{tn.Text}`", classDirective); - initialRoot.Type = new XamlIlAstClrTypeReference(classDirective, classType, false); + compiler.OverrideRootType(parsed, + new XamlIlAstClrTypeReference(classDirective, classType, false)); initialRoot.Children.Remove(classDirective); } diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs index 65149a65de..b84f50fa8d 100644 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs @@ -112,13 +112,31 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions rootType = new XamlIlAstClrTypeReference(rootObject, overrideRootType, false); } - rootObject.Type = rootType; + OverrideRootType(parsed, rootType); Transform(parsed); Compile(parsed, tb, _contextType, PopulateName, BuildName, "__AvaloniaXamlIlNsInfo", baseUri, fileSource); } - - + + public void OverrideRootType(XamlIlDocument doc, IXamlIlAstTypeReference newType) + { + var root = (XamlIlAstObjectNode)doc.Root; + var oldType = root.Type; + if (oldType.Equals(newType)) + return; + + root.Type = newType; + foreach (var child in root.Children.OfType()) + { + if (child.Property is XamlIlAstNamePropertyReference prop) + { + if (prop.DeclaringType.Equals(oldType)) + prop.DeclaringType = newType; + if (prop.TargetType.Equals(oldType)) + prop.TargetType = newType; + } + } + } } } diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs index f91e221ac0..70b7fe6aec 100644 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs @@ -4,6 +4,7 @@ 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 @@ -17,19 +18,24 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime { var resourceNodes = provider.GetService().Parents .OfType().ToList(); - - return sp => builder(new DeferredParentServiceProvider(sp, resourceNodes)); + var rootObject = provider.GetService().RootObject; + return sp => builder(new DeferredParentServiceProvider(sp, resourceNodes, rootObject)); } - class DeferredParentServiceProvider : IAvaloniaXamlIlParentStackProvider, IServiceProvider + class DeferredParentServiceProvider : + IAvaloniaXamlIlParentStackProvider, + IServiceProvider, + IRootObjectProvider { private readonly IServiceProvider _parentProvider; private readonly List _parentResourceNodes; - public DeferredParentServiceProvider(IServiceProvider parentProvider, List parentResourceNodes) + public DeferredParentServiceProvider(IServiceProvider parentProvider, List parentResourceNodes, + object rootObject) { _parentProvider = parentProvider; _parentResourceNodes = parentResourceNodes; + RootObject = rootObject; } public IEnumerable Parents => GetParents(); @@ -46,8 +52,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime { if (serviceType == typeof(IAvaloniaXamlIlParentStackProvider)) return this; + if (serviceType == typeof(IRootObjectProvider)) + return this; return _parentProvider?.GetService(serviceType); } + + public object RootObject { get; } } diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github b/src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github index 3b3c1f93a5..1e3ffc3154 160000 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github @@ -1 +1 @@ -Subproject commit 3b3c1f93a566080d417b9782f9cc4ea67cd62344 +Subproject commit 1e3ffc315401f0b2eb96a0e79b25c2fc19a80d78 diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj b/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj index c9eb72757f..3107f4cf22 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj @@ -32,7 +32,8 @@ Designer - + + diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlClassWithCustomProperty.xaml b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlClassWithCustomProperty.xaml new file mode 100644 index 0000000000..330561a2c6 --- /dev/null +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlClassWithCustomProperty.xaml @@ -0,0 +1,6 @@ + + + diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs index a584027768..795aba153a 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs @@ -5,8 +5,12 @@ using System.Globalization; using System.Linq; using System.Runtime.CompilerServices; using Avalonia.Controls; +using Avalonia.Controls.Presenters; using Avalonia.Data.Converters; +using Avalonia.Input; +using Avalonia.Interactivity; using Avalonia.Media; +using Avalonia.Threading; using Avalonia.UnitTests; using Avalonia.VisualTree; using JetBrains.Annotations; @@ -117,6 +121,81 @@ namespace Avalonia.Markup.Xaml.UnitTests Assert.Equal(Brushes.Red.Color, ((ISolidColorBrush)canvas.Background).Color); } } + + [Fact] + public void Event_Handlers_Should_Work_For_Templates() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var w =new XamlIlBugTestsEventHandlerCodeBehind(); + w.ApplyTemplate(); + w.Show(); + + Dispatcher.UIThread.RunJobs(); + var itemsPresenter = ((ItemsControl)w.Content).GetVisualChildren().FirstOrDefault(); + var item = itemsPresenter + .GetVisualChildren().First() + .GetVisualChildren().First() + .GetVisualChildren().First(); + ((Control)item).RaiseEvent(new PointerPressedEventArgs {ClickCount = 20}); + Assert.Equal(20, w.Args.ClickCount); + } + } + + [Fact] + public void Custom_Properties_Should_Work_With_XClass() + { + var precompiled = new XamlIlClassWithCustomProperty(); + Assert.Equal("123", precompiled.Test); + var loaded = (XamlIlClassWithCustomProperty)AvaloniaXamlLoader.Parse(@" + + +"); + Assert.Equal("321", loaded.Test); + + } + } + + public class XamlIlBugTestsEventHandlerCodeBehind : Window + { + public PointerPressedEventArgs Args; + public void HandlePointerPressed(object sender, PointerPressedEventArgs args) + { + Args = args; + } + + public XamlIlBugTestsEventHandlerCodeBehind() + { + new AvaloniaXamlLoader().Load(@" + + + + +