From a29837dd042b8ee068daef5049d1883cfe3d7189 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 9 Oct 2017 17:44:45 -0500 Subject: [PATCH] Implement syntax sugar for RelativeSource (not including setting a specific AncestorType) --- .../Avalonia.Markup.Xaml/Data/Binding.cs | 47 +++++++++-------- .../Xaml/BindingTests_RelativeSource.cs | 50 +++++++++++++++++++ 2 files changed, 75 insertions(+), 22 deletions(-) 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 = @" + + + +