Skip to content

XamlX update: IProvideValueTarget fixes and nested-types support #17021

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

Merged
merged 3 commits into from
Sep 14, 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
13 changes: 5 additions & 8 deletions samples/BindingDemo/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@
<Setter Property="FontSize" Value="18"/>
</Style>
</Window.Styles>
<Window.Resources>
<vm:TestItem x:Key="SharedItem" StringValue="shared" />
</Window.Resources>

<TabControl>
<TabItem Header="Basic">
Expand Down Expand Up @@ -54,9 +51,9 @@
<TextBox Watermark="Value of first TextBox" UseFloatingWatermark="True"
Text="{Binding #first.Text, Mode=TwoWay}"/>
<TextBox Watermark="Value of SharedItem.StringValue" UseFloatingWatermark="True"
Text="{Binding StringValue, Source={StaticResource SharedItem}, Mode=TwoWay}"/>
Text="{Binding StringValue, Source={StaticResource SharedItem}, Mode=TwoWay, DataType=vm:MainWindowViewModel+TestItem}"/>
<TextBox Watermark="Value of SharedItem.StringValue (duplicate)" UseFloatingWatermark="True"
Text="{Binding StringValue, Source={StaticResource SharedItem}, Mode=TwoWay}"/>
Text="{Binding StringValue, Source={StaticResource SharedItem}, Mode=TwoWay, DataType=vm:MainWindowViewModel+TestItem}"/>
</StackPanel>
<StackPanel Margin="18" Spacing="4" Width="200" HorizontalAlignment="Left">
<TextBlock FontSize="16" Text="Scheduler"/>
Expand All @@ -70,7 +67,7 @@
<TabItem Header="ListBox">
<StackPanel Orientation="Horizontal">
<StackPanel.DataTemplates>
<DataTemplate DataType="vm:TestItem">
<DataTemplate DataType="vm:MainWindowViewModel+TestItem">
<TextBlock Text="{Binding StringValue}"/>
</DataTemplate>
</StackPanel.DataTemplates>
Expand All @@ -84,7 +81,7 @@
</StackPanel>
<ContentControl Content="{ReflectionBinding Selection.SelectedItems[0]}">
<ContentControl.DataTemplates>
<DataTemplate DataType="vm:TestItem">
<DataTemplate DataType="vm:MainWindowViewModel+TestItem">
<local:TestItemView></local:TestItemView>
</DataTemplate>
</ContentControl.DataTemplates>
Expand Down Expand Up @@ -126,7 +123,7 @@
</TabItem.Resources>
<StackPanel>
<!-- Tests for #10856 -->
<TextBlock Text="{local:GenericMarkupExtension, Value=Red, x:TypeArguments=Color}"/>
<TextBlock Text="{local:GenericMarkupExtension Value=Red, x:TypeArguments=Color}"/>
<TextBlock HorizontalAlignment="Left"
Text="{Binding $self.Background, Converter={StaticResource BrushConverter}}">
<TextBlock.Background>
Expand Down
1 change: 1 addition & 0 deletions samples/BindingDemo/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public class MainWindow : Window
{
public MainWindow()
{
Resources["SharedItem"] = new MainWindowViewModel.TestItem() { StringValue = "shared" };
this.InitializeComponent();
this.DataContext = new MainWindowViewModel();
this.AttachDevTools();
Expand Down
2 changes: 1 addition & 1 deletion samples/BindingDemo/TestItemView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:viewModels="using:BindingDemo.ViewModels"
x:Class="BindingDemo.TestItemView"
x:DataType="viewModels:TestItem">
x:DataType="viewModels:MainWindowViewModel+TestItem">
<StackPanel>
<TextBlock Classes="h1" Text="{Binding StringValue}"/>
<TextBox Text="{Binding Detail}" AcceptsReturn="True"/>
Expand Down
19 changes: 19 additions & 0 deletions samples/BindingDemo/ViewModels/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,24 @@ bool CanDo(object parameter)
{
return BooleanFlag;
}

// Nested class, jsut so we can test it in XAML
public class TestItem : ViewModelBase
{
private string _stringValue = "String Value";
private string _detail;

public string StringValue
{
get { return _stringValue; }
set { this.RaiseAndSetIfChanged(ref this._stringValue, value); }
}

public string Detail
{
get { return _detail; }
set { this.RaiseAndSetIfChanged(ref this._detail, value); }
}
}
}
}
16 changes: 0 additions & 16 deletions samples/BindingDemo/ViewModels/TestItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,5 @@

namespace BindingDemo.ViewModels
{
public class TestItem : ViewModelBase
{
private string _stringValue = "String Value";
private string _detail;

public string StringValue
{
get { return _stringValue; }
set { this.RaiseAndSetIfChanged(ref this._stringValue, value); }
}

public string Detail
{
get { return _detail; }
set { this.RaiseAndSetIfChanged(ref this._detail, value); }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -334,13 +334,17 @@ public OptionsMarkupExtensionMethod(
public bool IsPrivate => false;
public bool IsFamily => false;
public bool IsStatic => false;
public bool ContainsGenericParameters => false;
public bool IsGenericMethod => false;
public bool IsGenericMethodDefinition => false;
public IXamlType ReturnType => ExtensionNodeContainer.GetReturnType();
public IReadOnlyList<IXamlType> Parameters { get; }
public IXamlType DeclaringType { get; }
public IXamlMethod MakeGenericMethod(IReadOnlyList<IXamlType> typeArguments) => throw new NotImplementedException();
public IReadOnlyList<IXamlCustomAttribute> CustomAttributes => Array.Empty<IXamlCustomAttribute>();

public IReadOnlyList<IXamlCustomAttribute> CustomAttributes => [];
public IXamlParameterInfo GetParameterInfo(int index) => new AnonymousParameterInfo(Parameters[index], index);
public IReadOnlyList<IXamlType> GenericParameters => [];
public IReadOnlyList<IXamlType> GenericArguments => [];

public void EmitCall(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ public GetterMethod(AvaloniaAttachedInstanceProperty parent)
public bool IsPrivate => false;
public bool IsFamily => false;
public bool IsStatic => true;
public bool ContainsGenericParameters => false;
public bool IsGenericMethod => false;
public bool IsGenericMethodDefinition => false;
public string Name { get; protected set; }
public IXamlType DeclaringType { get; }
public IXamlMethod MakeGenericMethod(IReadOnlyList<IXamlType> typeArguments)
Expand All @@ -181,6 +184,8 @@ public bool Equals(IXamlMethod? other) =>

public IReadOnlyList<IXamlCustomAttribute> CustomAttributes => DeclaringType.CustomAttributes;
public IXamlParameterInfo GetParameterInfo(int index) => new AnonymousParameterInfo(Parameters[index], index);
public IReadOnlyList<IXamlType> GenericParameters => [];
public IReadOnlyList<IXamlType> GenericArguments => [];

public void EmitCall(IXamlILEmitter emitter)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
Submodule xamlil.github updated 44 files
+59 −1 .editorconfig
+5 −0 Directory.Build.targets
+11 −3 XamlX.sln
+33 −12 src/XamlX.IL.Cecil/CecilAssembly.cs
+26 −5 src/XamlX.IL.Cecil/CecilMethod.cs
+3 −0 src/XamlX.IL.Cecil/CecilTypeBuilder.cs
+37 −2 src/XamlX.IL.Cecil/CecilTypeSystem.cs
+2 −1 src/XamlX.IL.Cecil/Comparers/TypeReferenceEqualityComparer.cs
+1 −1 src/XamlX.IL.Cecil/UnresolvedCecilType.cs
+4 −0 src/XamlX.IL.Cecil/XamlX.IL.Cecil.csproj
+8 −8 src/XamlX.Parser.GuiLabs/GuiLabsXamlParser.cs
+4 −0 src/XamlX.Runtime/XamlX.Runtime.csproj
+11 −1 src/XamlX/Ast/Clr.cs
+12 −0 src/XamlX/Compatibility/StringCompatibilityExtensions.cs
+1 −1 src/XamlX/Emit/XamlRuntimeContext.cs
+4 −0 src/XamlX/Extensions/TypeExtensions.cs
+6 −6 src/XamlX/IL/Emitters/PropertyAssignmentEmitter.cs
+1 −1 src/XamlX/IL/RecordingIlEmitter.cs
+34 −22 src/XamlX/IL/RuntimeContext.cs
+87 −41 src/XamlX/IL/SreTypeSystem.cs
+4 −4 src/XamlX/Parsers/SystemXamlMarkupExtensionParser/KnownStrings.cs
+7 −7 src/XamlX/Parsers/SystemXamlMarkupExtensionParser/MeScanner.Shims.cs
+1 −1 src/XamlX/Parsers/SystemXamlMarkupExtensionParser/MeScanner.cs
+8 −8 src/XamlX/Parsers/XDocumentXamlParser.cs
+1 −1 src/XamlX/Transform/Transformers/ConstructableObjectTransformer.cs
+1 −1 src/XamlX/Transform/Transformers/ResolvePropertyValueAddersTransformer.cs
+5 −0 src/XamlX/TypeSystem/TypeSystem.cs
+4 −0 src/XamlX/XamlX.csproj
+130 −0 tests/TypeSystemTest/BaseTest.Generics.cs
+40 −0 tests/TypeSystemTest/BaseTest.Nested_Types.cs
+91 −0 tests/TypeSystemTest/BaseTest.cs
+25 −0 tests/TypeSystemTest/CecilTest.cs
+9 −0 tests/TypeSystemTest/Models/Generics/ComplexGenericType.cs
+3 −0 tests/TypeSystemTest/Models/Generics/GenericBaseType{T}.cs
+8 −0 tests/TypeSystemTest/Models/Generics/GenericType.cs
+6 −0 tests/TypeSystemTest/Models/Generics/IGenericInterface{T}.cs
+23 −0 tests/TypeSystemTest/Models/Generics/TestType.cs
+19 −0 tests/TypeSystemTest/Models/NestedTyeps/InternaNestedTypeContainer.cs
+9 −0 tests/TypeSystemTest/Models/NestedTyeps/PrivateNestedTypeContainer.cs
+19 −0 tests/TypeSystemTest/Models/NestedTyeps/PublicNestedTypeContainer.cs
+18 −0 tests/TypeSystemTest/SreTest.cs
+12 −0 tests/TypeSystemTest/TypeSystemTest.csproj
+33 −0 tests/XamlParserTests/ServiceProviderTests.cs
+4 −4 tests/XamlParserTests/WhitespaceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<Compile Include="..\..\..\src\Markup\Avalonia.Markup.Xaml.Loader\CompilerDynamicDependencies.cs" />
<Compile Include="..\..\..\src\Avalonia.Base\Compatibility\NullableAttributes.cs" Link="Compatibility\NullableAttributes.cs" />
<Compile Include="..\..\..\src\Avalonia.Base\Compatibility\TrimmingAttributes.cs" Link="Compatibility\TrimmingAttributes.cs" />
<Compile Include="..\..\Shared\StringCompatibilityExtensions.cs" Link="Compatibility\StringCompatibilityExtensions.cs" />
<Compile Include="..\..\..\src\Shared\IsExternalInit.cs" Link="Compatibility\IsExternalInit.cs" />
</ItemGroup>
<Import Project="..\..\..\src\Markup\Avalonia.Markup.Xaml.Loader\IncludeXamlIlSre.props" />
Expand Down
9 changes: 9 additions & 0 deletions src/tools/Avalonia.Generators/Compiler/RoslynTypeSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,15 @@ other is RoslynMethod roslynMethod &&
public bool IsFamily => _symbol.DeclaredAccessibility == Accessibility.Protected;

public bool IsStatic => false;
public bool ContainsGenericParameters => _symbol.TypeParameters.Any();
public bool IsGenericMethod => _symbol.IsGenericMethod;
public bool IsGenericMethodDefinition => _symbol.IsDefinition && _symbol.IsGenericMethod;

public IReadOnlyList<IXamlType> GenericParameters => throw new NotImplementedException();

public IReadOnlyList<IXamlType> GenericArguments => _symbol.TypeArguments
.Select(ga => new RoslynType((INamedTypeSymbol)ga, _assembly))
.ToArray();

public IXamlType ReturnType => new RoslynType((INamedTypeSymbol) _symbol.ReturnType, _assembly);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia.Controls;
using Avalonia.Controls.Documents;
using Avalonia.Data;
using Avalonia.Data.Core;
using Avalonia.Markup.Xaml.MarkupExtensions;
using Avalonia.Media;
using Avalonia.UnitTests;
using Xunit;

namespace Avalonia.Markup.Xaml.UnitTests.Xaml;

public class ProvideValueTargetTests : XamlTestBase
{
[Fact]
public void ProvideValueTarget_Has_Correct_Targets_Set()
{
using var _ = UnitTestApplication.Start(TestServices.StyledWindow);

var capturedTargets = new CapturedTargets();
AvaloniaLocator.CurrentMutable.BindToSelf(capturedTargets);

AvaloniaRuntimeXamlLoader.Load(@"
<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'
Foreground='{local:CapturingTargetsMarkup}'
x:CompileBindings='True'>

<TextBlock Tag='{Binding Source={local:CapturingTargetsMarkup}}'
Background='{local:CapturingTargetsMarkup}' />

</Window>");

Assert.Collection(capturedTargets.Targets,
item =>
{
Assert.IsType<Window>(item.TargetObject);
Assert.Equal(TextElement.ForegroundProperty, item.TargetProperty);
},
item =>
{
Assert.IsAssignableFrom<CompiledBindingExtension>(item.TargetObject);
var prop = Assert.IsType<ClrPropertyInfo>(item.TargetProperty);
Assert.Equal(nameof(Binding.Source), prop.Name);
},
item =>
{
Assert.IsType<TextBlock>(item.TargetObject);
Assert.Equal(TextBlock.BackgroundProperty, item.TargetProperty);
});
}
}

public class CapturedTargets
{
public List<(object TargetObject, object TargetProperty)> Targets { get; } = [];
}

public class CapturingTargetsMarkupExtension
{
public object ProvideValue(IServiceProvider serviceProvider)
{
var parentsProvider = serviceProvider.GetRequiredService<IProvideValueTarget>();
var capturedTargets = AvaloniaLocator.Current.GetRequiredService<CapturedTargets>();
capturedTargets.Targets.Add((parentsProvider.TargetObject, parentsProvider.TargetProperty));
return Brushes.DarkViolet;
}
}
Loading