Browse Source

Merge pull request #10489 from AvaloniaUI/compiled-binding-fixes

Fix Relative Source with {x:Type} bindings
pull/10500/head
Max Katz 3 years ago
committed by GitHub
parent
commit
033c1e29ce
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 27
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs
  2. 62
      tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs

27
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs

@ -146,13 +146,23 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
.FirstOrDefault(x => x.Property.GetClrProperty().Name == "Tree")
?.Values[0] is XamlAstTextNode treeTypeValue ? treeTypeValue.Text : "Visual";
var ancestorTypeName = relativeSourceObject.Children
var ancestorType = relativeSourceObject.Children
.OfType<XamlAstXamlPropertyValueNode>()
.FirstOrDefault(x => x.Property.GetClrProperty().Name == "AncestorType")
?.Values[0] as XamlAstTextNode;
?.Values[0] switch
{
XamlAstTextNode textNode => TypeReferenceResolver.ResolveType(
context,
textNode.Text,
false,
textNode,
true).GetClrType(),
XamlTypeExtensionNode typeExtensionNode => typeExtensionNode.Value.GetClrType(),
null => null,
_ => throw new XamlParseException($"Unsupported node for AncestorType property", relativeSourceObject)
};
IXamlType ancestorType = null;
if (ancestorTypeName is null)
if (ancestorType is null)
{
if (treeType == "Visual")
{
@ -174,15 +184,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
}
}
else
{
ancestorType = TypeReferenceResolver.ResolveType(
context,
ancestorTypeName.Text,
false,
ancestorTypeName,
true).GetClrType();
}
if (treeType == "Visual")
{

62
tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs

@ -847,6 +847,30 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
Assert.Equal("test", target.Text);
}
}
[Fact]
public void ResolvesRelativeSourceBindingEvenLongerForm()
{
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.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
x:DataType='local:TestDataContext'
Title='test'>
<TextBlock Text='{CompiledBinding Title, RelativeSource={RelativeSource AncestorType={x:Type Window}}}' x:Name='text'/>
</Window>";
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var target = window.FindControl<TextBlock>("text");
window.ApplyTemplate();
window.Presenter.ApplyTemplate();
target.ApplyTemplate();
Assert.Equal("test", target.Text);
}
}
[Fact]
public void ResolvesRelativeSourceBindingFromTemplate()
@ -1735,7 +1759,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
<local:AssignBindingControl xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
X='{Binding StringProperty, DataType=local:TestDataContext}' />";
X='{CompiledBinding StringProperty, DataType=local:TestDataContext}' />";
var control = (AssignBindingControl)AvaloniaRuntimeXamlLoader.Load(new RuntimeXamlLoaderDocument(xaml),
new RuntimeXamlLoaderConfiguration { UseCompiledBindingsByDefault = true });
var compiledPath = ((CompiledBindingExtension)control.X).Path;
@ -1745,6 +1769,33 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
}
}
[Fact]
public void Should_Bind_To_Nested_Generic_Property()
{
// See https://github.com/AvaloniaUI/Avalonia/issues/10485
// This code works fine with SRE, and test is passing, but it fails on Cecil.
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.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
x:DataType='local:TestDataContext'
x:CompileBindings='True'>
<ComboBox x:Name='comboBox' Items='{Binding GenericProperty}' SelectedItem='{Binding GenericProperty.CurrentItem}' />
</Window>";
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var comboBox = window.FindControl<ComboBox>("comboBox");
var dataContext = new TestDataContext();
dataContext.GenericProperty.Add(123);
dataContext.GenericProperty.CurrentItem = 123;
window.DataContext = dataContext;
Assert.Equal(123, comboBox.SelectedItem);
}
}
static void Throws(string type, Action cb)
{
try
@ -1837,8 +1888,10 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
public string ExplicitProperty => "Bye";
public static string StaticProperty => "World";
public static string StaticProperty => "World";
public ListItemCollectionView<int> GenericProperty { get; } = new();
public class NonIntegerIndexer : NotifyingBase, INonIntegerIndexerDerived
{
private readonly Dictionary<string, string> _storage = new Dictionary<string, string>();
@ -1858,6 +1911,11 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
}
}
public class ListItemCollectionView<T> : List<T>
{
public T CurrentItem { get; set; }
}
public class MethodDataContext
{
public void Action() { }

Loading…
Cancel
Save