Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make complied bindings use TypeConverters again. #14767

Merged
merged 3 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .ncrunch/Avalonia.FreeDesktop.net6.0.v3.ncrunchproject
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>
3 changes: 3 additions & 0 deletions .ncrunch/Avalonia.Themes.Simple.net6.0.v3.ncrunchproject
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<ProjectConfiguration>
<Settings>
<AdditionalFilesToIncludeForProject>
<Value>..\Avalonia.Themes.Fluent\Strings\InvariantResources.xaml</Value>
</AdditionalFilesToIncludeForProject>
<InstrumentOutputAssembly>False</InstrumentOutputAssembly>
</Settings>
</ProjectConfiguration>
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<ProjectConfiguration>
<Settings>
<AdditionalFilesToIncludeForProject>
<Value>..\Avalonia.Themes.Fluent\Strings\InvariantResources.xaml</Value>
</AdditionalFilesToIncludeForProject>
<InstrumentOutputAssembly>False</InstrumentOutputAssembly>
</Settings>
</ProjectConfiguration>
5 changes: 5 additions & 0 deletions .ncrunch/Avalonia.X11.net6.0.v3.ncrunchproject
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>
5 changes: 5 additions & 0 deletions .ncrunch/Avalonia.X11.netstandard2.0.v3.ncrunchproject
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>
46 changes: 35 additions & 11 deletions src/Avalonia.Base/Data/Core/TargetTypeConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Windows.Input;
using Avalonia.Utilities;
using static Avalonia.Utilities.TypeUtilities;
using System.ComponentModel;

namespace Avalonia.Data.Core;

Expand Down Expand Up @@ -65,6 +66,40 @@ public override bool TryConvert(object? value, Type type, CultureInfo culture, o
return true;
}

#pragma warning disable IL2026
#pragma warning disable IL2067
// TODO: TypeConverters are not trimming friendly in some edge cases, we probably need
// to make compiled bindings emit conversion code at compile-time.
var toTypeConverter = TypeDescriptor.GetConverter(t);
var from = value.GetType();

if (toTypeConverter.CanConvertFrom(from))
{
result = toTypeConverter.ConvertFrom(null, culture, value);
return true;
}

var fromTypeConverter = TypeDescriptor.GetConverter(from);

if (fromTypeConverter.CanConvertTo(t))
{
result = fromTypeConverter.ConvertTo(null, culture, value, t);
return true;
}

// TODO: This requires reflection: we probably need to make compiled bindings emit
// conversion code at compile-time.
if (FindTypeConversionOperatorMethod(
value.GetType(),
t,
OperatorType.Implicit | OperatorType.Explicit) is { } cast)
{
result = cast.Invoke(null, new[] { value });
return true;
}
#pragma warning restore IL2067
#pragma warning restore IL2026

if (value is IConvertible convertible)
{
try
Expand All @@ -79,17 +114,6 @@ public override bool TryConvert(object? value, Type type, CultureInfo culture, o
}
}

// TODO: This requires reflection: we probably need to make compiled bindings emit
// conversion code at compile-time.
if (FindTypeConversionOperatorMethod(
value.GetType(),
t,
OperatorType.Implicit | OperatorType.Explicit) is { } cast)
{
result = cast.Invoke(null, new[] { value });
return true;
}

result = null;
return false;
}
Expand Down
24 changes: 24 additions & 0 deletions tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
using Avalonia.Controls.Presenters;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Avalonia.Media;
using Avalonia.Media.Immutable;
using Avalonia.UnitTests;
using Avalonia.VisualTree;
using Xunit;
Expand Down Expand Up @@ -94,6 +96,28 @@ public void MultiBinding_TemplatedParent_Works()
Assert.Equal("Foo,Bar", target.Text);
}
}

[Fact]
public void Can_Bind_Brush_to_Hex_String()
{
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.Data;assembly=Avalonia.Markup.Xaml.UnitTests'>
<Border Background='{Binding HexString}'/>
</Window>";
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var border = (Border)window.Content;
window.DataContext = new { HexString = "#ff0000" };

window.ApplyTemplate();

var brush = Assert.IsType<ImmutableSolidColorBrush>(border.Background);
Assert.Equal(Colors.Red, brush.Color);
}
}
}

public class ConcatConverter : IMultiValueConverter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings;
using Avalonia.Markup.Xaml.Templates;
using Avalonia.Media;
using Avalonia.Media.Immutable;
using Avalonia.Metadata;
using Avalonia.UnitTests;
using Xunit;
Expand Down Expand Up @@ -2022,6 +2023,30 @@ public void Can_Use_Implicit_Conversions()
}
}

[Fact]
public void Can_Bind_Brush_To_Hex_String()
{
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:TestData'
x:CompileBindings='True'>
<TextBlock Name='textBlock' Background='{{Binding StringProperty}}'/>
</Window>";
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var textBlock = window.FindControl<TextBlock>("textBlock");

var dataContext = new TestData { StringProperty = "#ff0000" };
window.DataContext = dataContext;

var brush = Assert.IsType<ImmutableSolidColorBrush>(textBlock!.Background);
Assert.Equal(Colors.Red, brush.Color);
}
}

static void Throws(string type, Action cb)
{
try
Expand Down
Loading