diff --git a/src/Markup/Avalonia.Markup.Xaml/Data/Binding.cs b/src/Markup/Avalonia.Markup.Xaml/Data/Binding.cs
index 9d911999c6..052f743a4b 100644
--- a/src/Markup/Avalonia.Markup.Xaml/Data/Binding.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/Data/Binding.cs
@@ -96,7 +96,7 @@ namespace Avalonia.Markup.Xaml.Data
ValidateState(pathInfo);
enableDataValidation = enableDataValidation && Priority == BindingPriority.LocalValue;
- var elementName = pathInfo.ElementName;
+ var elementName = ElementName ?? pathInfo.ElementName;
var relativeSource = RelativeSource ?? pathInfo.RelativeSource;
ExpressionObserver observer;
@@ -213,38 +213,41 @@ namespace Avalonia.Markup.Xaml.Data
relativeSource.Mode = RelativeSourceMode.Self;
}
else if(relativeSourceMode == "parent")
+ {
+ relativeSource.Mode = RelativeSourceMode.FindAncestor;
+ relativeSource.AncestorType = typeof(IControl);
+ relativeSource.AncestorLevel = 1;
+ }
+ else if(relativeSourceMode.StartsWith("parent["))
{
relativeSource.Mode = RelativeSourceMode.FindAncestor;
var parentConfigStart = relativeSourceMode.IndexOf('[');
- if (parentConfigStart != -1)
+ if (!relativeSourceMode.EndsWith("]"))
{
- if (!relativeSourceMode.EndsWith("]"))
- {
- throw new InvalidOperationException("Invalid RelativeSource binding syntax. Expected matching ']' for '['.");
- }
- var parentConfigParams = relativeSourceMode.Substring(0, relativeSourceMode.Length - 1).Split(',');
- if (parentConfigParams.Length > 2 || parentConfigParams.Length == 0)
- {
- throw new InvalidOperationException("Expected either 1 or 2 parameters for RelativeSource binding syntax");
- }
- else if (parentConfigParams.Length == 1)
+ throw new InvalidOperationException("Invalid RelativeSource binding syntax. Expected matching ']' for '['.");
+ }
+ var parentConfigParams = relativeSourceMode.Substring(parentConfigStart + 1).TrimEnd(']').Split(',');
+ if (parentConfigParams.Length > 2 || parentConfigParams.Length == 0)
+ {
+ throw new InvalidOperationException("Expected either 1 or 2 parameters for RelativeSource binding syntax");
+ }
+ else if (parentConfigParams.Length == 1)
+ {
+ if (int.TryParse(parentConfigParams[0], out int level))
{
- if (int.TryParse(parentConfigParams[0], out int level))
- {
- relativeSource.AncestorType = typeof(IControl);
- relativeSource.AncestorLevel = level;
- }
- else
- {
- relativeSource.AncestorType = LookupAncestorType(parentConfigParams[0]);
- }
+ relativeSource.AncestorType = typeof(IControl);
+ relativeSource.AncestorLevel = level + 1;
}
else
{
relativeSource.AncestorType = LookupAncestorType(parentConfigParams[0]);
- relativeSource.AncestorLevel = int.Parse(parentConfigParams[1]);
}
}
+ else
+ {
+ relativeSource.AncestorType = LookupAncestorType(parentConfigParams[0]);
+ relativeSource.AncestorLevel = int.Parse(parentConfigParams[1]) + 1;
+ }
}
else
{
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BindingTests_RelativeSource.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BindingTests_RelativeSource.cs
index 9125e1e643..a4e4d4f5c3 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BindingTests_RelativeSource.cs
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BindingTests_RelativeSource.cs
@@ -77,6 +77,31 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
}
}
+ [Fact]
+ public void Binding_To_First_Ancestor_With_Shorthand_Works()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+
+
+
+
+";
+ var loader = new AvaloniaXamlLoader();
+ var window = (Window)loader.Load(xaml);
+ var button = window.FindControl