Browse Source

Implement syntax sugar for RelativeSource (not including setting a specific AncestorType)

pull/1209/head
Jeremy Koritzinsky 9 years ago
parent
commit
a29837dd04
  1. 47
      src/Markup/Avalonia.Markup.Xaml/Data/Binding.cs
  2. 50
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BindingTests_RelativeSource.cs

47
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
{

50
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 = @"
<Window xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
<Border Name='border1'>
<Border Name='border2'>
<Button Name='button' Content='{Binding $parent.Name}'/>
</Border>
</Border>
</Window>";
var loader = new AvaloniaXamlLoader();
var window = (Window)loader.Load(xaml);
var button = window.FindControl<Button>("button");
window.ApplyTemplate();
Assert.Equal("border2", button.Content);
}
}
[Fact]
public void Binding_To_Second_Ancestor_Works()
{
@ -102,6 +127,31 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
}
}
[Fact]
public void Binding_To_Second_Ancestor_With_Shorthand_Works()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
<Border Name='border1'>
<Border Name='border2'>
<Button Name='button' Content='{Binding $parent[1].Name}'/>
</Border>
</Border>
</Window>";
var loader = new AvaloniaXamlLoader();
var window = (Window)loader.Load(xaml);
var button = window.FindControl<Button>("button");
window.ApplyTemplate();
Assert.Equal("border1", button.Content);
}
}
[Fact]
public void Binding_To_Ancestor_With_Namespace_Works()
{

Loading…
Cancel
Save