diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
index 09e6b27967..3e4204d79d 100644
--- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
+++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
@@ -46,6 +46,7 @@
+
diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs
index 710faa28f4..396196cfbc 100644
--- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs
@@ -53,6 +53,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
// After everything else
+ InsertBefore(
+ new AvaloniaXamlIlBindingPathParser()
+ );
+
InsertBefore(
new AddNameScopeRegistration(),
new AvaloniaXamlIlDataContextTypeTransformer(),
diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs
new file mode 100644
index 0000000000..9a34261813
--- /dev/null
+++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Avalonia.Markup.Parsers;
+using Avalonia.Utilities;
+using XamlIl.Ast;
+using XamlIl.Transform;
+using XamlIl.TypeSystem;
+
+namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
+{
+ class AvaloniaXamlIlBindingPathParser : IXamlIlAstTransformer
+ {
+ public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
+ {
+ if (node is XamlIlAstObjectNode binding && binding.Type.GetClrType().Equals(context.GetAvaloniaTypes().CompiledBindingExtension))
+ {
+ if (binding.Arguments.Count > 0 && binding.Arguments[0] is XamlIlAstTextNode bindingPathText)
+ {
+ var reader = new CharacterReader(bindingPathText.Text.AsSpan());
+ var (nodes, _) = BindingExpressionGrammar.Parse(ref reader);
+ binding.Arguments[0] = new ParsedBindingPathNode(bindingPathText, context.GetAvaloniaTypes().CompiledBindingPath, nodes);
+ }
+ else
+ {
+ var bindingPathAssignment = binding.Children.OfType()
+ .FirstOrDefault(v => v.Property.GetClrProperty().Name == "Path");
+
+ if (bindingPathAssignment != null && bindingPathAssignment.Values[0] is XamlIlAstTextNode pathValue)
+ {
+ var reader = new CharacterReader(pathValue.Text.AsSpan());
+ var (nodes, _) = BindingExpressionGrammar.Parse(ref reader);
+ bindingPathAssignment.Values[0] = new ParsedBindingPathNode(pathValue, context.GetAvaloniaTypes().CompiledBindingPath, nodes);
+ }
+ }
+ }
+
+ return node;
+ }
+ }
+
+ class ParsedBindingPathNode : XamlIlAstNode, IXamlIlAstValueNode
+ {
+ public ParsedBindingPathNode(IXamlIlLineInfo lineInfo, IXamlIlType compiledBindingType, IList path)
+ : base(lineInfo)
+ {
+ Type = new XamlIlAstClrTypeReference(lineInfo, compiledBindingType, false);
+ Path = path;
+ }
+
+ public IXamlIlAstTypeReference Type { get; }
+
+ public IList Path { get; }
+ }
+}
diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/XamlIlBindingPathHelper.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/XamlIlBindingPathHelper.cs
index 1a4facf543..69512dcf75 100644
--- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/XamlIlBindingPathHelper.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/XamlIlBindingPathHelper.cs
@@ -19,40 +19,34 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public static IXamlIlType UpdateCompiledBindingExtension(XamlIlAstTransformationContext context, XamlIlAstObjectNode binding, IXamlIlType startType)
{
IXamlIlType bindingResultType = null;
- if (binding.Arguments.Count > 0 && binding.Arguments[0] is XamlIlAstTextNode bindingPathText)
+ if (binding.Arguments.Count > 0 && binding.Arguments[0] is ParsedBindingPathNode bindingPath)
{
- var reader = new CharacterReader(bindingPathText.Text.AsSpan());
- var grammar = BindingExpressionGrammar.Parse(ref reader);
-
var transformed = TransformBindingPath(
context,
- bindingPathText,
+ bindingPath,
startType,
- grammar.Nodes);
+ bindingPath.Path);
bindingResultType = transformed.BindingResultType;
binding.Arguments[0] = transformed;
}
else
{
- var bindingPathAssignment = binding.Children.OfType()
- .FirstOrDefault(v => v.Property.GetClrProperty().Name == "Path");
+ var bindingPathAssignment = binding.Children.OfType()
+ .FirstOrDefault(v => v.Property.Name == "Path");
if (bindingPathAssignment is null)
{
return startType;
}
- if (bindingPathAssignment.Values[0] is XamlIlAstTextNode pathValue)
+ if (bindingPathAssignment.Values[0] is ParsedBindingPathNode bindingPathNode)
{
- var reader = new CharacterReader(pathValue.Text.AsSpan());
- var grammar = BindingExpressionGrammar.Parse(ref reader);
-
var transformed = TransformBindingPath(
context,
- pathValue,
+ bindingPathNode,
startType,
- grammar.Nodes);
+ bindingPathNode.Path);
bindingResultType = transformed.BindingResultType;
bindingPathAssignment.Values[0] = transformed;
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs
index 3de6e035ba..0648ca6571 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs
@@ -32,7 +32,32 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
var window = (Window)loader.Load(xaml);
var textBlock = window.FindControl("textBlock");
- DelayedBinding.ApplyBindings(textBlock);
+ var dataContext = new TestDataContext
+ {
+ StringProperty = "foobar"
+ };
+
+ window.DataContext = dataContext;
+
+ Assert.Equal(dataContext.StringProperty, textBlock.Text);
+ }
+ }
+
+ [Fact]
+ public void ResolvesPathPassedByProperty()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+";
+ var loader = new AvaloniaXamlLoader();
+ var window = (Window)loader.Load(xaml);
+ var textBlock = window.FindControl("textBlock");
var dataContext = new TestDataContext
{
@@ -61,8 +86,6 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
var window = (Window)loader.Load(xaml);
var textBlock = window.FindControl("textBlock");
- DelayedBinding.ApplyBindings(textBlock);
-
var dataContext = new TestDataContext
{
TaskProperty = Task.FromResult("foobar")