diff --git a/samples/BindingDemo/BindingDemo.csproj b/samples/BindingDemo/BindingDemo.csproj
index faeb643d8a..33c6aa1440 100644
--- a/samples/BindingDemo/BindingDemo.csproj
+++ b/samples/BindingDemo/BindingDemo.csproj
@@ -2,6 +2,7 @@
Exe
$(AvsCurrentTargetFramework)
+
diff --git a/samples/BindingDemo/MainWindow.xaml b/samples/BindingDemo/MainWindow.xaml
index ed23f68d91..9d68c8da8a 100644
--- a/samples/BindingDemo/MainWindow.xaml
+++ b/samples/BindingDemo/MainWindow.xaml
@@ -3,6 +3,7 @@
x:Class="BindingDemo.MainWindow"
xmlns:vm="using:BindingDemo.ViewModels"
xmlns:local="using:BindingDemo"
+ xmlns:system="clr-namespace:System;assembly=System.Runtime"
Title="AvaloniaUI Bindings Test"
Width="800"
Height="600"
@@ -29,7 +30,7 @@
-
+
@@ -51,9 +52,9 @@
+ Text="{Binding Value, Source={StaticResource SharedItem}, Mode=TwoWay, DataType={x:Type vm:MainWindowViewModel+TestItem, x:TypeArguments=x:String}}"/>
+ Text="{Binding Value, Source={StaticResource SharedItem}, Mode=TwoWay, DataType={x:Type vm:MainWindowViewModel+TestItem, x:TypeArguments=x:String}}"/>
@@ -67,8 +68,8 @@
-
-
+
+
@@ -81,7 +82,7 @@
-
+
diff --git a/samples/BindingDemo/MainWindow.xaml.cs b/samples/BindingDemo/MainWindow.xaml.cs
index 57466fe581..36d4feb108 100644
--- a/samples/BindingDemo/MainWindow.xaml.cs
+++ b/samples/BindingDemo/MainWindow.xaml.cs
@@ -9,7 +9,7 @@ namespace BindingDemo
{
public MainWindow()
{
- Resources["SharedItem"] = new MainWindowViewModel.TestItem() { StringValue = "shared" };
+ Resources["SharedItem"] = new MainWindowViewModel.TestItem() { Value = "shared" };
this.InitializeComponent();
this.DataContext = new MainWindowViewModel();
this.AttachDevTools();
diff --git a/samples/BindingDemo/TestItemView.xaml b/samples/BindingDemo/TestItemView.xaml
index 6eb59ffc83..fcf3a80ceb 100644
--- a/samples/BindingDemo/TestItemView.xaml
+++ b/samples/BindingDemo/TestItemView.xaml
@@ -2,9 +2,9 @@
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:viewModels="using:BindingDemo.ViewModels"
x:Class="BindingDemo.TestItemView"
- x:DataType="viewModels:MainWindowViewModel+TestItem">
+ x:DataType="{x:Type viewModels:MainWindowViewModel+TestItem, x:TypeArguments=x:String}">
-
+
diff --git a/samples/BindingDemo/ViewModels/MainWindowViewModel.cs b/samples/BindingDemo/ViewModels/MainWindowViewModel.cs
index f5f4f3531f..eb1a007695 100644
--- a/samples/BindingDemo/ViewModels/MainWindowViewModel.cs
+++ b/samples/BindingDemo/ViewModels/MainWindowViewModel.cs
@@ -23,14 +23,14 @@ namespace BindingDemo.ViewModels
public MainWindowViewModel()
{
- Items = new ObservableCollection(
- Enumerable.Range(0, 20).Select(x => new TestItem
+ Items = new ObservableCollection>(
+ Enumerable.Range(0, 20).Select(x => new TestItem
{
- StringValue = "Item " + x,
+ Value = "Item " + x,
Detail = "Item " + x + " details",
}));
- Selection = new SelectionModel { SingleSelect = false };
+ Selection = new SelectionModel> { SingleSelect = false };
ShuffleItems = MiniCommand.Create(() =>
{
@@ -58,8 +58,8 @@ namespace BindingDemo.ViewModels
.Select(x => DateTimeOffset.Now);
}
- public ObservableCollection Items { get; }
- public SelectionModel Selection { get; }
+ public ObservableCollection> Items { get; }
+ public SelectionModel> Selection { get; }
public MiniCommand ShuffleItems { get; }
public string BooleanString
@@ -117,15 +117,15 @@ namespace BindingDemo.ViewModels
}
// Nested class, jsut so we can test it in XAML
- public class TestItem : ViewModelBase
+ public class TestItem : ViewModelBase
{
- private string _stringValue = "String Value";
+ private T _value;
private string _detail;
- public string StringValue
+ public T Value
{
- get { return _stringValue; }
- set { this.RaiseAndSetIfChanged(ref this._stringValue, value); }
+ get { return _value; }
+ set { this.RaiseAndSetIfChanged(ref this._value, value); }
}
public string Detail
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDataContextTypeTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDataContextTypeTransformer.cs
index 6b4f32bce0..8632ea6ee0 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDataContextTypeTransformer.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDataContextTypeTransformer.cs
@@ -44,7 +44,11 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
on.Children.RemoveAt(i);
i--;
- if (directive.Values[0] is XamlAstTextNode text)
+ if (directive.Values[0] is XamlTypeExtensionNode typeNode)
+ {
+ directiveDataContextTypeNode = new AvaloniaXamlIlDataContextTypeMetadataNode(on, typeNode.Value.GetClrType());
+ }
+ else if (directive.Values[0] is XamlAstTextNode text)
{
directiveDataContextTypeNode = new AvaloniaXamlIlDataContextTypeMetadataNode(on,
TypeReferenceResolver.ResolveType(context, text.Text, isMarkupExtension: false, text, strict: true).Type);
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs
index 727ebeab40..61b3024f65 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs
@@ -244,7 +244,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
window.DataContext = dataContext;
- Assert.Equal(dataContext.TaskProperty.Result, textBlock.Text);
+ Assert.Equal("foobar", textBlock.Text);
}
}
@@ -1320,6 +1320,28 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
}
}
+ [Fact]
+ public void SupportsParentInPathWithTypeAndLevelFilter()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(@"
+
+
+
+
+
+
+");
+ var textBlock = window.GetControl("textBlock");
+
+ Assert.Equal("p1", textBlock.Text);
+ }
+ }
+
[Fact]
public void SupportConverterWithParameter()
{
@@ -1936,7 +1958,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
[Theory]
[InlineData(null, "Not called")]
[InlineData("A", "Do A")]
- public void Binding_Method_With_Parameter_To_Command_CanExecute(object commandParameter, string result)
+ public void Binding_Method_With_Parameter_To_Command_CanExecute(object? commandParameter, string result)
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
@@ -2213,6 +2235,37 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
}
}
+ [Fact]
+ public void Resolves_Nested_Generic_DataTypes()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(@"
+
+
+
+
+");
+ var textBlock = window.GetControl("textBlock");
+
+ var dataContext = new TestDataContext
+ {
+ NestedGenericString = new TestDataContext.NestedGeneric
+ {
+ Value = "10"
+ }
+ };
+
+ window.DataContext = dataContext.NestedGenericString;
+
+ Assert.Equal(dataContext.NestedGenericString.Value, textBlock.Text);
+ }
+ }
+
static void Throws(string type, Action cb)
{
try
@@ -2303,7 +2356,9 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
public INonIntegerIndexerDerived NonIntegerIndexerInterfaceProperty => NonIntegerIndexerProperty;
- string IHasExplicitProperty.ExplicitProperty => "Hello";
+ public NestedGeneric? NestedGenericString { get; init; }
+
+ string IHasExplicitProperty.ExplicitProperty => "Hello";
public string ExplicitProperty => "Bye";
@@ -2328,6 +2383,11 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
}
}
}
+
+ public class NestedGeneric
+ {
+ public T Value { get; set; }
+ }
}
public class ListItemCollectionView : List