Browse Source

Handle $self in compiled binding in multibinding. (#14935)

pull/14954/head
Johan Appelgren 2 years ago
committed by GitHub
parent
commit
84b06b22d4
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 7
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathTransformer.cs
  2. 2
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
  3. 68
      tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs

7
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathTransformer.cs

@ -123,7 +123,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
};
var selfType = context.ParentNodes().OfType<XamlAstConstructableObjectNode>().First().Type.GetClrType();
if (context.GetAvaloniaTypes().MultiBinding.IsAssignableFrom(selfType))
{
selfType = context.ParentNodes().OfType<XamlAstConstructableObjectNode>().Skip(1).First().Type.GetClrType();
}
// When using self bindings with setters we need to change target type to resolved selector type.
if (context.GetAvaloniaTypes().SetterBase.IsAssignableFrom(selfType))
{

2
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs

@ -21,6 +21,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlMethod AvaloniaObjectSetStyledPropertyValue { get; }
public IXamlType AvaloniaAttachedPropertyT { get; }
public IXamlType IBinding { get; }
public IXamlType MultiBinding { get; }
public IXamlMethod AvaloniaObjectBindMethod { get; }
public IXamlMethod AvaloniaObjectSetValueMethod { get; }
public IXamlType IDisposable { get; }
@ -140,6 +141,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
&& m.Parameters[0].Name == "StyledProperty`1"
&& m.Parameters[2].Equals(BindingPriority));
IBinding = cfg.TypeSystem.GetType("Avalonia.Data.IBinding");
MultiBinding = cfg.TypeSystem.GetType("Avalonia.Data.MultiBinding");
IDisposable = cfg.TypeSystem.GetType("System.IDisposable");
ICommand = cfg.TypeSystem.GetType("System.Windows.Input.ICommand");
Transitions = cfg.TypeSystem.GetType("Avalonia.Animation.Transitions");

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

@ -1692,6 +1692,74 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
}
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void Binds_To_RelativeSource_Self_In_MultiBinding(bool compileBindings)
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var xaml = $@"
<Window xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
x:CompileBindings='{compileBindings}'>
<StackPanel>
<TextBlock Name='textBlock'>
<TextBlock.Text>
<MultiBinding StringFormat=""{{}} $self = {{0}}, $parent = {{1}}"">
<Binding Path=""$self.FontStyle""/>
<Binding Path=""$parent.Orientation""/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</Window>";
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var textBlock = window.GetControl<TextBlock>("textBlock");
var dataContext = new TestDataContext();
window.DataContext = dataContext;
Assert.Equal(" $self = Normal, $parent = Vertical"
, textBlock.GetValue(TextBlock.TextProperty));
}
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void Binds_To_RelativeSource_Self_In_MultiBinding_In_Style(bool compileBindings)
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var xaml = $@"
<Window xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
x:CompileBindings='{compileBindings}'>
<Window.Styles>
<Style Selector='TextBlock'>
<Setter Property='Text'>
<MultiBinding StringFormat=""{{}} $self = {{0}}"">
<Binding Path=""$self.FontStyle""/>
</MultiBinding>
</Setter>
</Style>
</Window.Styles>
<StackPanel>
<TextBlock Name='textBlock'/>
</StackPanel>
</Window>";
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var textBlock = window.GetControl<TextBlock>("textBlock");
var dataContext = new TestDataContext();
window.DataContext = dataContext;
Assert.Equal(" $self = Normal"
, textBlock.GetValue(TextBlock.TextProperty));
}
}
[Fact]
public void SupportsMethodBindingAsDelegate()
{

Loading…
Cancel
Save