diff --git a/samples/BindingDemo/MainWindow.xaml b/samples/BindingDemo/MainWindow.xaml
index 08ac0426ea2..d1c65ca73b0 100644
--- a/samples/BindingDemo/MainWindow.xaml
+++ b/samples/BindingDemo/MainWindow.xaml
@@ -75,11 +75,11 @@
-
+
-
+
diff --git a/samples/ControlCatalog/Pages/TabControlPage.xaml b/samples/ControlCatalog/Pages/TabControlPage.xaml
index a775056ebe9..3a2464e9fdb 100644
--- a/samples/ControlCatalog/Pages/TabControlPage.xaml
+++ b/samples/ControlCatalog/Pages/TabControlPage.xaml
@@ -51,7 +51,7 @@
Text="From DataTemplate">
diff --git a/samples/VirtualizationDemo/MainWindow.xaml b/samples/VirtualizationDemo/MainWindow.xaml
index 235f3ef2cc4..3aee63c2464 100644
--- a/samples/VirtualizationDemo/MainWindow.xaml
+++ b/samples/VirtualizationDemo/MainWindow.xaml
@@ -11,7 +11,7 @@
Margin="16 0 0 0"
Width="150"
Spacing="4">
-
Horiz. ScrollBar
-
Vert. ScrollBar
-
is defined on the ItemTemplate property,
/// allowing the template to inherit the data type from the Items collection binding.
///
-[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
+[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class InheritDataTypeFromItemsAttribute : Attribute
{
///
diff --git a/src/Avalonia.Controls/Flyouts/MenuFlyout.cs b/src/Avalonia.Controls/Flyouts/MenuFlyout.cs
index ba5489ac251..8e1bc214a7b 100644
--- a/src/Avalonia.Controls/Flyouts/MenuFlyout.cs
+++ b/src/Avalonia.Controls/Flyouts/MenuFlyout.cs
@@ -90,7 +90,7 @@ protected override Control CreatePresenter()
{
return new MenuFlyoutPresenter
{
- [!ItemsControl.ItemsProperty] = this[!ItemsProperty],
+ [!ItemsControl.ItemsSourceProperty] = this[!ItemsProperty],
[!ItemsControl.ItemTemplateProperty] = this[!ItemTemplateProperty],
[!ItemsControl.ItemContainerThemeProperty] = this[!ItemContainerThemeProperty],
};
diff --git a/src/Avalonia.Controls/ItemCollection.cs b/src/Avalonia.Controls/ItemCollection.cs
index c9265558f0f..03f46551c5f 100644
--- a/src/Avalonia.Controls/ItemCollection.cs
+++ b/src/Avalonia.Controls/ItemCollection.cs
@@ -106,19 +106,6 @@ private IList WritableSource
}
}
- internal IList? GetItemsPropertyValue()
- {
- if (_mode == Mode.ObsoleteItemsSetter)
- return Source == s_uninitialized ? null : Source;
- return this;
- }
-
- internal void SetItems(IList? items)
- {
- _mode = Mode.ObsoleteItemsSetter;
- SetSource(items ?? s_uninitialized);
- }
-
internal void SetItemsSource(IEnumerable? value)
{
if (_mode != Mode.ItemsSource && Count > 0)
@@ -159,7 +146,6 @@ private enum Mode
{
Items,
ItemsSource,
- ObsoleteItemsSetter,
}
}
}
diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs
index 1123f42afa8..6a914281479 100644
--- a/src/Avalonia.Controls/ItemsControl.cs
+++ b/src/Avalonia.Controls/ItemsControl.cs
@@ -30,17 +30,6 @@ public class ItemsControl : TemplatedControl, IChildIndexProvider, IScrollSnapPo
private static readonly FuncTemplate DefaultPanel =
new(() => new StackPanel());
- ///
- /// Defines the property.
- ///
- public static readonly DirectProperty ItemsProperty =
- AvaloniaProperty.RegisterDirect(
- nameof(Items),
- o => o.Items,
-#pragma warning disable CS0618 // Type or member is obsolete
- (o, v) => o.Items = v);
-#pragma warning restore CS0618 // Type or member is obsolete
-
///
/// Defines the property.
///
@@ -94,7 +83,6 @@ public class ItemsControl : TemplatedControl, IChildIndexProvider, IScrollSnapPo
///
[AssignBinding]
[InheritDataTypeFromItems(nameof(ItemsSource))]
- [InheritDataTypeFromItems(nameof(Items))]
public IBinding? DisplayMemberBinding
{
get => GetValue(DisplayMemberBindingProperty);
@@ -129,48 +117,20 @@ public ItemContainerGenerator ItemContainerGenerator
}
///
- /// Gets or sets the items to display.
+ /// Gets the items to display.
///
///
- /// Since Avalonia 11, has both an property
- /// and an property. The properties have the following differences:
- ///
- ///
- /// - is initialized with an empty collection and is a direct property,
- /// meaning that it cannot be styled
- /// - is by default null, and is a styled property. This property
- /// is marked as the content property and will be used for items added via inline XAML.
- ///
- ///
- /// In Avalonia 11 the two properties can be used almost interchangeably but this will change
- /// in a later version. In order to be ready for this change, follow the following guidance:
- ///
- ///
- /// - You should use the property when you're assigning a collection of
- /// item containers directly, for example adding a collection of s
- /// directly to a . Add the containers to the pre-existing list, do not
- /// reassign the property via the setter or with a binding.
- /// - You should use the property when you're assigning or
- /// binding a collection of models which will be transformed by a data template.
- ///
+ /// You use either the or the property to
+ /// specify the collection that should be used to generate the content of your
+ /// . When the property is set, the
+ /// collection is made read-only and fixed-size.
+ ///
+ /// When is in use, setting the
+ /// property to null removes the collection and restores usage to ,
+ /// which will be an empty .
///
[Content]
- public IList? Items
- {
- get => _items.GetItemsPropertyValue();
-
- [Obsolete("Use ItemsSource to set or bind items.")]
- set
- {
- var oldItems = _items.GetItemsPropertyValue();
-
- if (value != oldItems)
- {
- _items.SetItems(value);
- RaisePropertyChanged(ItemsProperty, oldItems, value);
- }
- }
- }
+ public ItemCollection Items => _items;
///
/// Gets or sets the that is applied to the container element generated for each item.
@@ -210,27 +170,17 @@ public ITemplate ItemsPanel
/// Gets or sets a collection used to generate the content of the .
///
///
- /// Since Avalonia 11, has both an property
- /// and an property. The properties have the following differences:
- ///
- ///
- /// - is initialized with an empty collection and is a direct property,
- /// meaning that it cannot be styled
- /// - is by default null, and is a styled property. This property
- /// is marked as the content property and will be used for items added via inline XAML.
- ///
- ///
- /// In Avalonia 11 the two properties can be used almost interchangeably but this will change
- /// in a later version. In order to be ready for this change, follow the following guidance:
+ /// A common scenario is to use an such as a
+ /// to display a data collection, or to bind an
+ /// to a collection object. To bind an
+ /// to a collection object, use the property.
///
- ///
- /// - You should use the property when you're assigning a collection of
- /// item containers directly, for example adding a collection of s
- /// directly to a . Add the containers to the pre-existing list, do not
- /// reassign the property via the setter or with a binding.
- /// - You should use the property when you're assigning or
- /// binding a collection of models which will be transformed by a data template.
- ///
+ /// When the property is set, the collection
+ /// is made read-only and fixed-size.
+ ///
+ /// When is in use, setting the property to null removes the
+ /// collection and restores usage to , which will be an empty
+ /// .
///
public IEnumerable? ItemsSource
{
@@ -242,7 +192,6 @@ public IEnumerable? ItemsSource
/// 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/HeaderedItemsControl.cs b/src/Avalonia.Controls/Primitives/HeaderedItemsControl.cs
index 55d2ec7506d..89f99682673 100644
--- a/src/Avalonia.Controls/Primitives/HeaderedItemsControl.cs
+++ b/src/Avalonia.Controls/Primitives/HeaderedItemsControl.cs
@@ -124,7 +124,7 @@ internal void PrepareItemContainer()
treeTemplate.Match(item) &&
treeTemplate.ItemsSelector(item) is { } itemsBinding)
{
- _itemsBinding = BindingOperations.Apply(this, ItemsProperty, itemsBinding, null);
+ _itemsBinding = BindingOperations.Apply(this, ItemsSourceProperty, itemsBinding, null);
}
}
diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
index b89a75787f6..9c060f2258f 100644
--- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
+++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
@@ -235,7 +235,6 @@ public object? SelectedItem
///
[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 681d2a38d46..a24d4eb6e96 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDataContextTypeTransformer.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDataContextTypeTransformer.cs
@@ -73,32 +73,27 @@ public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode nod
// Infer data type from collection binding on a control that displays items.
var property = context.ParentNodes().OfType().FirstOrDefault();
var attributeType = context.GetAvaloniaTypes().InheritDataTypeFromItemsAttribute;
- var attributes = property?.Property?.GetClrProperty().CustomAttributes
- .Where(a => a.Type == attributeType).ToList();
-
- if (attributes?.Count > 0)
+ var attribute = property?.Property?.GetClrProperty().CustomAttributes
+ .FirstOrDefault(a => a.Type == attributeType);
+
+ if (attribute is not null)
{
- foreach (var attribute in attributes)
+ var propertyName = (string)attribute.Parameters.First();
+ XamlAstConstructableObjectNode parentObject;
+ if (attribute.Properties.TryGetValue("AncestorType", out var type)
+ && type is IXamlType xamlType)
{
- 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;
- }
+ 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);
}
}
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlBindingTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlBindingTests.cs
index affa292a7d7..6018e2438f6 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlBindingTests.cs
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlBindingTests.cs
@@ -73,14 +73,14 @@ public void Can_Bind_Between_TabStrip_And_Carousel()
var xaml = @"
-
+
-
+