Skip to content
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
4 changes: 2 additions & 2 deletions samples/BindingDemo/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,11 @@
</StackPanel.DataTemplates>
<StackPanel Margin="18" Spacing="4" Width="200">
<TextBlock FontSize="16" Text="Multiple"/>
<ListBox Items="{Binding Items}" SelectionMode="Multiple" Selection="{Binding Selection}"/>
<ListBox ItemsSource="{Binding Items}" SelectionMode="Multiple" Selection="{Binding Selection}"/>
</StackPanel>
<StackPanel Margin="18" Spacing="4" Width="200">
<TextBlock FontSize="16" Text="Multiple"/>
<ListBox Items="{Binding Items}" SelectionMode="Multiple" Selection="{Binding Selection}"/>
<ListBox ItemsSource="{Binding Items}" SelectionMode="Multiple" Selection="{Binding Selection}"/>
</StackPanel>
<ContentControl Content="{ReflectionBinding Selection.SelectedItems[0]}">
<ContentControl.DataTemplates>
Expand Down
2 changes: 1 addition & 1 deletion samples/ControlCatalog/Pages/TabControlPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
Text="From DataTemplate">
</TextBlock>
<TabControl
Items="{Binding Tabs}"
ItemsSource="{Binding Tabs}"
Margin="0 16"
DisplayMemberBinding="{Binding Header, x:DataType=viewModels:TabControlPageViewModelItem}"
TabStripPlacement="{Binding TabPlacement}">
Expand Down
8 changes: 4 additions & 4 deletions samples/VirtualizationDemo/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
Margin="16 0 0 0"
Width="150"
Spacing="4">
<ComboBox Items="{Binding Orientations}"
<ComboBox ItemsSource="{Binding Orientations}"
SelectedItem="{Binding Orientation}"/>
<TextBox Watermark="Item Count"
UseFloatingWatermark="True"
Expand All @@ -26,10 +26,10 @@
UseFloatingWatermark="True"
Text="{Binding #listBox.Scroll.Viewport, Mode=OneWay}"/>
<TextBlock>Horiz. ScrollBar</TextBlock>
<ComboBox Items="{Binding ScrollBarVisibilities}"
<ComboBox ItemsSource="{Binding ScrollBarVisibilities}"
SelectedItem="{Binding HorizontalScrollBarVisibility}"/>
<TextBlock>Vert. ScrollBar</TextBlock>
<ComboBox Items="{Binding ScrollBarVisibilities}"
<ComboBox ItemsSource="{Binding ScrollBarVisibilities}"
SelectedItem="{Binding VerticalScrollBarVisibility}"/>
<TextBox Watermark="Item to Create"
UseFloatingWatermark="True"
Expand All @@ -44,7 +44,7 @@
</StackPanel>

<ListBox Name="listBox"
Items="{Binding Items}"
ItemsSource="{Binding Items}"
Selection="{Binding Selection}"
SelectionMode="Multiple"
ScrollViewer.HorizontalScrollBarVisibility="{Binding HorizontalScrollBarVisibility, Mode=TwoWay}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Avalonia.Metadata;
/// A typical usage example is a ListBox control, where <see cref="InheritDataTypeFromItemsAttribute"/> is defined on the ItemTemplate property,
/// allowing the template to inherit the data type from the Items collection binding.
/// </remarks>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class InheritDataTypeFromItemsAttribute : Attribute
{
/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Avalonia.Controls/Flyouts/MenuFlyout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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],
};
Expand Down
14 changes: 0 additions & 14 deletions src/Avalonia.Controls/ItemCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -159,7 +146,6 @@ private enum Mode
{
Items,
ItemsSource,
ObsoleteItemsSetter,
}
}
}
91 changes: 20 additions & 71 deletions src/Avalonia.Controls/ItemsControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,6 @@ public class ItemsControl : TemplatedControl, IChildIndexProvider, IScrollSnapPo
private static readonly FuncTemplate<Panel?> DefaultPanel =
new(() => new StackPanel());

/// <summary>
/// Defines the <see cref="Items"/> property.
/// </summary>
public static readonly DirectProperty<ItemsControl, IList?> ItemsProperty =
AvaloniaProperty.RegisterDirect<ItemsControl, IList?>(
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

/// <summary>
/// Defines the <see cref="ItemContainerTheme"/> property.
/// </summary>
Expand Down Expand Up @@ -94,7 +83,6 @@ public class ItemsControl : TemplatedControl, IChildIndexProvider, IScrollSnapPo
/// </summary>
[AssignBinding]
[InheritDataTypeFromItems(nameof(ItemsSource))]
[InheritDataTypeFromItems(nameof(Items))]
public IBinding? DisplayMemberBinding
{
get => GetValue(DisplayMemberBindingProperty);
Expand Down Expand Up @@ -129,48 +117,20 @@ public ItemContainerGenerator ItemContainerGenerator
}

/// <summary>
/// Gets or sets the items to display.
/// Gets the items to display.
/// </summary>
/// <remarks>
/// Since Avalonia 11, <see cref="ItemsControl"/> has both an <see cref="Items"/> property
/// and an <see cref="ItemsSource"/> property. The properties have the following differences:
///
/// <list type="bullet">
/// <item><see cref="Items"/> is initialized with an empty collection and is a direct property,
/// meaning that it cannot be styled </item>
/// <item><see cref="ItemsSource"/> 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.</item>
/// </list>
///
/// 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:
///
/// <list type="bullet">
/// <item>You should use the <see cref="Items"/> property when you're assigning a collection of
/// item containers directly, for example adding a collection of <see cref="ListBoxItem"/>s
/// directly to a <see cref="ListBox"/>. Add the containers to the pre-existing list, do not
/// reassign the <see cref="Items"/> property via the setter or with a binding.</item>
/// <item>You should use the <see cref="ItemsSource"/> property when you're assigning or
/// binding a collection of models which will be transformed by a data template.</item>
/// </list>
/// You use either the <see cref="Items"/> or the <see cref="ItemsSource"/> property to
/// specify the collection that should be used to generate the content of your
/// <see cref="ItemsControl"/>. When the <see cref="ItemsSource"/> property is set, the
/// <see cref="Items"/> collection is made read-only and fixed-size.
///
/// When <see cref="ItemsSource"/> is in use, setting the <see cref="ItemsSource"/>
/// property to null removes the collection and restores usage to <see cref="Items"/>,
/// which will be an empty <see cref="ItemCollection"/>.
/// </remarks>
[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;

/// <summary>
/// Gets or sets the <see cref="ControlTheme"/> that is applied to the container element generated for each item.
Expand Down Expand Up @@ -210,27 +170,17 @@ public ITemplate<Panel?> ItemsPanel
/// Gets or sets a collection used to generate the content of the <see cref="ItemsControl"/>.
/// </summary>
/// <remarks>
/// Since Avalonia 11, <see cref="ItemsControl"/> has both an <see cref="Items"/> property
/// and an <see cref="ItemsSource"/> property. The properties have the following differences:
///
/// <list type="bullet">
/// <item><see cref="Items"/> is initialized with an empty collection and is a direct property,
/// meaning that it cannot be styled </item>
/// <item><see cref="ItemsSource"/> 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.</item>
/// </list>
///
/// 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 <see cref="ItemsControl"/> such as a
/// <see cref="ListBox"/> to display a data collection, or to bind an
/// <see cref="ItemsControl"/> to a collection object. To bind an <see cref="ItemsControl"/>
/// to a collection object, use the <see cref="ItemsSource"/> property.
///
/// <list type="bullet">
/// <item>You should use the <see cref="Items"/> property when you're assigning a collection of
/// item containers directly, for example adding a collection of <see cref="ListBoxItem"/>s
/// directly to a <see cref="ListBox"/>. Add the containers to the pre-existing list, do not
/// reassign the <see cref="Items"/> property via the setter or with a binding.</item>
/// <item>You should use the <see cref="ItemsSource"/> property when you're assigning or
/// binding a collection of models which will be transformed by a data template.</item>
/// </list>
/// When the <see cref="ItemsSource"/> property is set, the <see cref="Items"/> collection
/// is made read-only and fixed-size.
///
/// When <see cref="ItemsSource"/> is in use, setting the property to null removes the
/// collection and restores usage to <see cref="Items"/>, which will be an empty
/// <see cref="ItemCollection"/>.
/// </remarks>
public IEnumerable? ItemsSource
{
Expand All @@ -242,7 +192,6 @@ public IEnumerable? ItemsSource
/// Gets or sets the data template used to display the items in the control.
/// </summary>
[InheritDataTypeFromItems(nameof(ItemsSource))]
[InheritDataTypeFromItems(nameof(Items))]
public IDataTemplate? ItemTemplate
{
get => GetValue(ItemTemplateProperty);
Expand Down
2 changes: 1 addition & 1 deletion src/Avalonia.Controls/Primitives/HeaderedItemsControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
1 change: 0 additions & 1 deletion src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,6 @@ public object? SelectedItem
/// </summary>
[AssignBinding]
[InheritDataTypeFromItems(nameof(ItemsSource))]
[InheritDataTypeFromItems(nameof(Items))]
public IBinding? SelectedValueBinding
{
get => GetValue(SelectedValueBindingProperty);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<XamlPropertyAssignmentNode>().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<XamlAstConstructableObjectNode>()
.FirstOrDefault(n => n.Type.GetClrType().FullName == xamlType.FullName);
}
else
{
parentObject = context.ParentNodes().OfType<XamlAstConstructableObjectNode>().FirstOrDefault();
}

if (parentObject != null)
{
inferredDataContextTypeNode = InferDataContextOfPresentedItem(context, on, parentObject, propertyName);
if (inferredDataContextTypeNode != null)
break;
}
parentObject = context.ParentNodes().OfType<XamlAstConstructableObjectNode>()
.FirstOrDefault(n => n.Type.GetClrType().FullName == xamlType.FullName);
}
else
{
parentObject = context.ParentNodes().OfType<XamlAstConstructableObjectNode>().FirstOrDefault();
}

if (parentObject != null)
{
inferredDataContextTypeNode = InferDataContextOfPresentedItem(context, on, parentObject, propertyName);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,14 @@ public void Can_Bind_Between_TabStrip_And_Carousel()
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'>
<DockPanel>
<TabStrip Name='strip' DockPanel.Dock='Top' Items='{Binding Items}' SelectedIndex='0'>
<TabStrip Name='strip' DockPanel.Dock='Top' ItemsSource='{Binding Items}' SelectedIndex='0'>
<TabStrip.ItemTemplate>
<DataTemplate>
<TextBlock Text='{Binding Header}'/>
</DataTemplate>
</TabStrip.ItemTemplate>
</TabStrip>
<Carousel Name='carousel' Items='{Binding Items}' SelectedIndex='{Binding #strip.SelectedIndex}'>
<Carousel Name='carousel' ItemsSource='{Binding Items}' SelectedIndex='{Binding #strip.SelectedIndex}'>
<Carousel.ItemTemplate>
<DataTemplate>
<TextBlock Text='{Binding Detail}'/>
Expand Down