diff --git a/samples/BindingDemo/MainWindow.xaml b/samples/BindingDemo/MainWindow.xaml
index f14ad59cd5..ed23f68d91 100644
--- a/samples/BindingDemo/MainWindow.xaml
+++ b/samples/BindingDemo/MainWindow.xaml
@@ -12,9 +12,6 @@
-
-
-
@@ -54,9 +51,9 @@
+ Text="{Binding StringValue, Source={StaticResource SharedItem}, Mode=TwoWay, DataType=vm:MainWindowViewModel+TestItem}"/>
+ Text="{Binding StringValue, Source={StaticResource SharedItem}, Mode=TwoWay, DataType=vm:MainWindowViewModel+TestItem}"/>
@@ -70,7 +67,7 @@
-
+
@@ -84,7 +81,7 @@
-
+
@@ -126,7 +123,7 @@
-
+
diff --git a/samples/BindingDemo/MainWindow.xaml.cs b/samples/BindingDemo/MainWindow.xaml.cs
index eaa57e1f5f..57466fe581 100644
--- a/samples/BindingDemo/MainWindow.xaml.cs
+++ b/samples/BindingDemo/MainWindow.xaml.cs
@@ -9,6 +9,7 @@ namespace BindingDemo
{
public MainWindow()
{
+ Resources["SharedItem"] = new MainWindowViewModel.TestItem() { StringValue = "shared" };
this.InitializeComponent();
this.DataContext = new MainWindowViewModel();
this.AttachDevTools();
diff --git a/samples/BindingDemo/TestItemView.xaml b/samples/BindingDemo/TestItemView.xaml
index 6edade34b2..6eb59ffc83 100644
--- a/samples/BindingDemo/TestItemView.xaml
+++ b/samples/BindingDemo/TestItemView.xaml
@@ -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">
diff --git a/samples/BindingDemo/ViewModels/MainWindowViewModel.cs b/samples/BindingDemo/ViewModels/MainWindowViewModel.cs
index 18a7a01a69..f5f4f3531f 100644
--- a/samples/BindingDemo/ViewModels/MainWindowViewModel.cs
+++ b/samples/BindingDemo/ViewModels/MainWindowViewModel.cs
@@ -115,5 +115,24 @@ namespace BindingDemo.ViewModels
{
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); }
+ }
+ }
}
}
diff --git a/samples/BindingDemo/ViewModels/TestItem.cs b/samples/BindingDemo/ViewModels/TestItem.cs
index 2f49a3c99f..2e11f63e95 100644
--- a/samples/BindingDemo/ViewModels/TestItem.cs
+++ b/samples/BindingDemo/ViewModels/TestItem.cs
@@ -2,21 +2,5 @@ using MiniMvvm;
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); }
- }
- }
}
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlOptionMarkupExtensionTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlOptionMarkupExtensionTransformer.cs
index b6e2744125..104859d438 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlOptionMarkupExtensionTransformer.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlOptionMarkupExtensionTransformer.cs
@@ -334,13 +334,17 @@ internal class AvaloniaXamlIlOptionMarkupExtensionTransformer : IXamlAstTransfor
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 Parameters { get; }
public IXamlType DeclaringType { get; }
public IXamlMethod MakeGenericMethod(IReadOnlyList typeArguments) => throw new NotImplementedException();
- public IReadOnlyList CustomAttributes => Array.Empty();
-
+ public IReadOnlyList CustomAttributes => [];
public IXamlParameterInfo GetParameterInfo(int index) => new AnonymousParameterInfo(Parameters[index], index);
+ public IReadOnlyList GenericParameters => [];
+ public IReadOnlyList GenericArguments => [];
public void EmitCall(XamlEmitContext context, IXamlILEmitter codeGen)
{
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformInstanceAttachedProperties.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformInstanceAttachedProperties.cs
index 34e8e0974b..5668fa2b73 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformInstanceAttachedProperties.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformInstanceAttachedProperties.cs
@@ -168,6 +168,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
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 typeArguments)
@@ -181,6 +184,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IReadOnlyList CustomAttributes => DeclaringType.CustomAttributes;
public IXamlParameterInfo GetParameterInfo(int index) => new AnonymousParameterInfo(Parameters[index], index);
+ public IReadOnlyList GenericParameters => [];
+ public IReadOnlyList GenericArguments => [];
public void EmitCall(IXamlILEmitter emitter)
{
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github b/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
index 14fed0cb06..ab84721302 160000
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
@@ -1 +1 @@
-Subproject commit 14fed0cb0666a9b3f71cb635cf61eb6010d4ff64
+Subproject commit ab84721302d6ed2b8b65315f3c54217693640348
diff --git a/src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj b/src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj
index 4255813c5f..e4f78f304f 100644
--- a/src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj
+++ b/src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj
@@ -16,6 +16,7 @@
+
diff --git a/src/tools/Avalonia.Generators/Compiler/RoslynTypeSystem.cs b/src/tools/Avalonia.Generators/Compiler/RoslynTypeSystem.cs
index d2034d96ae..7e0ab123f4 100644
--- a/src/tools/Avalonia.Generators/Compiler/RoslynTypeSystem.cs
+++ b/src/tools/Avalonia.Generators/Compiler/RoslynTypeSystem.cs
@@ -297,6 +297,15 @@ internal class RoslynMethod : IXamlMethod
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 GenericParameters => throw new NotImplementedException();
+
+ public IReadOnlyList GenericArguments => _symbol.TypeArguments
+ .Select(ga => new RoslynType((INamedTypeSymbol)ga, _assembly))
+ .ToArray();
public IXamlType ReturnType => new RoslynType((INamedTypeSymbol) _symbol.ReturnType, _assembly);
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ProvideValueTargetTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ProvideValueTargetTests.cs
new file mode 100644
index 0000000000..6df31f55f2
--- /dev/null
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ProvideValueTargetTests.cs
@@ -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(@"
+
+
+
+
+");
+
+ Assert.Collection(capturedTargets.Targets,
+ item =>
+ {
+ Assert.IsType(item.TargetObject);
+ Assert.Equal(TextElement.ForegroundProperty, item.TargetProperty);
+ },
+ item =>
+ {
+ Assert.IsAssignableFrom(item.TargetObject);
+ var prop = Assert.IsType(item.TargetProperty);
+ Assert.Equal(nameof(Binding.Source), prop.Name);
+ },
+ item =>
+ {
+ Assert.IsType(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();
+ var capturedTargets = AvaloniaLocator.Current.GetRequiredService();
+ capturedTargets.Targets.Add((parentsProvider.TargetObject, parentsProvider.TargetProperty));
+ return Brushes.DarkViolet;
+ }
+}