diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs index 24cded1d229..890cbb69bf9 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs @@ -9,7 +9,6 @@ using XamlX.Transform; using XamlX.Transform.Transformers; using XamlX.TypeSystem; - using XamlParseException = XamlX.XamlParseException; namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers @@ -21,6 +20,7 @@ public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode nod if (node is XamlAstObjectNode binding && binding.Type.GetClrType().Equals(context.GetAvaloniaTypes().CompiledBindingExtension)) { var convertedNode = ConvertLongFormPropertiesToBindingExpressionNode(context, binding); + var foundPath = false; if (binding.Arguments.Count > 0 && binding.Arguments[0] is XamlAstTextNode bindingPathText) { @@ -32,9 +32,18 @@ public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode nod nodes.Insert(nodes.TakeWhile(x => x is BindingExpressionGrammar.ITransformNode).Count(), convertedNode); } - binding.Arguments[0] = new ParsedBindingPathNode(bindingPathText, context.GetAvaloniaTypes().CompiledBindingPath, nodes); + if (nodes.Count == 1 && nodes[0] is BindingExpressionGrammar.EmptyExpressionNode) + { + binding.Arguments.RemoveAt(0); + } + else + { + binding.Arguments[0] = new ParsedBindingPathNode(bindingPathText, context.GetAvaloniaTypes().CompiledBindingPath, nodes); + foundPath = true; + } } - else + + if (!foundPath) { var bindingPathAssignment = binding.Children.OfType() .FirstOrDefault(v => v.Property.GetClrProperty().Name == "Path"); @@ -44,12 +53,19 @@ public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode nod var reader = new CharacterReader(pathValue.Text.AsSpan()); var (nodes, _) = BindingExpressionGrammar.Parse(ref reader); - if (convertedNode != null) + if (nodes.Count == 1 && nodes[0] is BindingExpressionGrammar.EmptyExpressionNode) { - nodes.Insert(nodes.TakeWhile(x => x is BindingExpressionGrammar.ITransformNode).Count(), convertedNode); + bindingPathAssignment.Values.RemoveAt(0); } + else + { + if (convertedNode != null) + { + nodes.Insert(nodes.TakeWhile(x => x is BindingExpressionGrammar.ITransformNode).Count(), convertedNode); + } - bindingPathAssignment.Values[0] = new ParsedBindingPathNode(pathValue, context.GetAvaloniaTypes().CompiledBindingPath, nodes); + bindingPathAssignment.Values[0] = new ParsedBindingPathNode(pathValue, context.GetAvaloniaTypes().CompiledBindingPath, nodes); + } } } } diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs index 6f549a4ffa8..8a61458030a 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs @@ -938,6 +938,110 @@ public void SupportCastToTypeInExpressionWithProperty_DifferentTypeEvaluatesToNu } } + [Fact] + public void SupportsEmptyPath() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var xaml = @" + + +"; + var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml); + var textBlock = window.FindControl("textBlock"); + + var dataContext = new TestDataContext + { + StringProperty = "foobar" + }; + + window.DataContext = dataContext; + + Assert.Equal(typeof(TestDataContext).FullName, textBlock.Text); + } + } + + [Fact] + public void SupportsEmptyPathWithStringFormat() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var xaml = @" + + +"; + var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml); + var textBlock = window.FindControl("textBlock"); + + var dataContext = new TestDataContext + { + StringProperty = "foobar" + }; + + window.DataContext = dataContext; + + Assert.Equal("bar-" + typeof(TestDataContext).FullName, textBlock.Text); + } + } + + [Fact] + public void SupportsDotPath() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var xaml = @" + + +"; + var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml); + var textBlock = window.FindControl("textBlock"); + + var dataContext = new TestDataContext + { + StringProperty = "foobar" + }; + + window.DataContext = dataContext; + + Assert.Equal(typeof(TestDataContext).FullName, textBlock.Text); + } + } + + [Fact] + public void SupportsExplicitDotPathWithStringFormat() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var xaml = @" + + +"; + var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml); + var textBlock = window.FindControl("textBlock"); + + var dataContext = new TestDataContext + { + StringProperty = "foobar" + }; + + window.DataContext = dataContext; + + Assert.Equal("bar-" + typeof(TestDataContext).FullName, textBlock.Text); + } + } + void Throws(string type, Action cb) { try