diff --git a/src/Avalonia.Base/Metadata/InheritDataTypeFromItemsAttribute.cs b/src/Avalonia.Base/Metadata/InheritDataTypeFromItemsAttribute.cs index fac8cd8737..e9bd6ab89f 100644 --- a/src/Avalonia.Base/Metadata/InheritDataTypeFromItemsAttribute.cs +++ b/src/Avalonia.Base/Metadata/InheritDataTypeFromItemsAttribute.cs @@ -9,7 +9,7 @@ namespace Avalonia.Metadata; /// A typical usage example is a ListBox control, where is defined on the ItemTemplate property, /// allowing the template to inherit the data type from the Items collection binding. /// -[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] +[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)] public sealed class InheritDataTypeFromItemsAttribute : Attribute { /// diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 56ba9c7183..4914a833de 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -95,6 +95,7 @@ namespace Avalonia.Controls /// [AssignBinding] [InheritDataTypeFromItems(nameof(ItemsSource))] + [InheritDataTypeFromItems(nameof(Items))] public IBinding? DisplayMemberBinding { get => GetValue(DisplayMemberBindingProperty); @@ -218,6 +219,7 @@ namespace Avalonia.Controls /// Gets or sets the data template used to display the items in the control. /// [InheritDataTypeFromItems(nameof(ItemsSource))] + [InheritDataTypeFromItems(nameof(Items))] public IDataTemplate? ItemTemplate { get => GetValue(ItemTemplateProperty); diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs index 7716e32e26..a31472fab4 100644 --- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs +++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs @@ -235,6 +235,7 @@ namespace Avalonia.Controls.Primitives /// [AssignBinding] [InheritDataTypeFromItems(nameof(ItemsSource))] + [InheritDataTypeFromItems(nameof(Items))] public IBinding? SelectedValueBinding { get => GetValue(SelectedValueBindingProperty); 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 a24d4eb6e9..681d2a38d4 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDataContextTypeTransformer.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDataContextTypeTransformer.cs @@ -73,27 +73,32 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers // Infer data type from collection binding on a control that displays items. var property = context.ParentNodes().OfType().FirstOrDefault(); var attributeType = context.GetAvaloniaTypes().InheritDataTypeFromItemsAttribute; - var attribute = property?.Property?.GetClrProperty().CustomAttributes - .FirstOrDefault(a => a.Type == attributeType); - - if (attribute is not null) + var attributes = property?.Property?.GetClrProperty().CustomAttributes + .Where(a => a.Type == attributeType).ToList(); + + if (attributes?.Count > 0) { - var propertyName = (string)attribute.Parameters.First(); - XamlAstConstructableObjectNode parentObject; - if (attribute.Properties.TryGetValue("AncestorType", out var type) - && type is IXamlType xamlType) - { - parentObject = context.ParentNodes().OfType() - .FirstOrDefault(n => n.Type.GetClrType().FullName == xamlType.FullName); - } - else + foreach (var attribute in attributes) { - parentObject = context.ParentNodes().OfType().FirstOrDefault(); - } - - if (parentObject != null) - { - inferredDataContextTypeNode = InferDataContextOfPresentedItem(context, on, parentObject, propertyName); + var propertyName = (string)attribute.Parameters.First(); + XamlAstConstructableObjectNode parentObject; + if (attribute.Properties.TryGetValue("AncestorType", out var type) + && type is IXamlType xamlType) + { + parentObject = context.ParentNodes().OfType() + .FirstOrDefault(n => n.Type.GetClrType().FullName == xamlType.FullName); + } + else + { + parentObject = context.ParentNodes().OfType().FirstOrDefault(); + } + + if (parentObject != null) + { + inferredDataContextTypeNode = InferDataContextOfPresentedItem(context, on, parentObject, propertyName); + if (inferredDataContextTypeNode != null) + break; + } } }