diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 06427991f8..83aa88a7b6 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -23,7 +23,7 @@ namespace Avalonia.Controls /// Displays a collection of items. /// [PseudoClasses(":empty", ":singleitem")] - public class ItemsControl : TemplatedControl, IChildIndexProvider, IScrollSnapPointsInfo + public class ItemsControl : TemplatedControl, IChildIndexProvider { /// /// The default value for the property. @@ -67,18 +67,6 @@ namespace Avalonia.Controls public static readonly StyledProperty DisplayMemberBindingProperty = AvaloniaProperty.Register(nameof(DisplayMemberBinding)); - /// - /// Defines the property. - /// - public static readonly StyledProperty AreHorizontalSnapPointsRegularProperty = - AvaloniaProperty.Register(nameof(AreHorizontalSnapPointsRegular)); - - /// - /// Defines the property. - /// - public static readonly StyledProperty AreVerticalSnapPointsRegularProperty = - AvaloniaProperty.Register(nameof(AreVerticalSnapPointsRegular)); - /// /// Gets or sets the to use for binding to the display member of each item. /// @@ -249,64 +237,6 @@ namespace Avalonia.Controls /// public event EventHandler? ContainerClearing; - /// - public event EventHandler HorizontalSnapPointsChanged - { - add - { - if (_itemsPresenter != null) - { - _itemsPresenter.HorizontalSnapPointsChanged += value; - } - } - - remove - { - if (_itemsPresenter != null) - { - _itemsPresenter.HorizontalSnapPointsChanged -= value; - } - } - } - - /// - public event EventHandler VerticalSnapPointsChanged - { - add - { - if (_itemsPresenter != null) - { - _itemsPresenter.VerticalSnapPointsChanged += value; - } - } - - remove - { - if (_itemsPresenter != null) - { - _itemsPresenter.VerticalSnapPointsChanged -= value; - } - } - } - - /// - /// Gets or sets whether the horizontal snap points for the are equidistant from each other. - /// - public bool AreHorizontalSnapPointsRegular - { - get => GetValue(AreHorizontalSnapPointsRegularProperty); - set => SetValue(AreHorizontalSnapPointsRegularProperty, value); - } - - /// - /// Gets or sets whether the vertical snap points for the are equidistant from each other. - /// - public bool AreVerticalSnapPointsRegular - { - get => GetValue(AreVerticalSnapPointsRegularProperty); - set => SetValue(AreVerticalSnapPointsRegularProperty, value); - } - /// /// Gets a default recycle key that can be used when an supports /// a single container type. @@ -896,19 +826,5 @@ namespace Avalonia.Controls count = ItemsView.Count; return true; } - - /// - public IReadOnlyList GetIrregularSnapPoints(Orientation orientation, SnapPointsAlignment snapPointsAlignment) - { - return _itemsPresenter?.GetIrregularSnapPoints(orientation, snapPointsAlignment) ?? new List(); - } - - /// - public double GetRegularSnapPoints(Orientation orientation, SnapPointsAlignment snapPointsAlignment, out double offset) - { - offset = 0; - - return _itemsPresenter?.GetRegularSnapPoints(orientation, snapPointsAlignment, out offset) ?? 0; - } } } diff --git a/src/Avalonia.Controls/Presenters/ItemsPresenter.cs b/src/Avalonia.Controls/Presenters/ItemsPresenter.cs index 9610be088b..63e512492e 100644 --- a/src/Avalonia.Controls/Presenters/ItemsPresenter.cs +++ b/src/Avalonia.Controls/Presenters/ItemsPresenter.cs @@ -11,7 +11,7 @@ namespace Avalonia.Controls.Presenters /// /// Presents items inside an . /// - public class ItemsPresenter : Control, ILogicalScrollable, IScrollSnapPointsInfo + public class ItemsPresenter : Control, ILogicalScrollable { /// /// Defines the property. @@ -21,37 +21,8 @@ namespace Avalonia.Controls.Presenters private PanelContainerGenerator? _generator; private ILogicalScrollable? _logicalScrollable; - private IScrollSnapPointsInfo? _scrollSnapPointsInfo; private EventHandler? _scrollInvalidated; - /// - /// Defines the property. - /// - public static readonly StyledProperty AreHorizontalSnapPointsRegularProperty = - AvaloniaProperty.Register(nameof(AreHorizontalSnapPointsRegular)); - - /// - /// Defines the property. - /// - public static readonly StyledProperty AreVerticalSnapPointsRegularProperty = - AvaloniaProperty.Register(nameof(AreVerticalSnapPointsRegular)); - - /// - /// Defines the event. - /// - public static readonly RoutedEvent HorizontalSnapPointsChangedEvent = - RoutedEvent.Register( - nameof(HorizontalSnapPointsChanged), - RoutingStrategies.Bubble); - - /// - /// Defines the event. - /// - public static readonly RoutedEvent VerticalSnapPointsChangedEvent = - RoutedEvent.Register( - nameof(VerticalSnapPointsChanged), - RoutingStrategies.Bubble); - event EventHandler? ILogicalScrollable.ScrollInvalidated { add => _scrollInvalidated += value; @@ -107,47 +78,12 @@ namespace Avalonia.Controls.Presenters } } - /// - /// Occurs when the measurements for horizontal snap points change. - /// - public event EventHandler? HorizontalSnapPointsChanged - { - add => AddHandler(HorizontalSnapPointsChangedEvent, value); - remove => RemoveHandler(HorizontalSnapPointsChangedEvent, value); - } - - /// - /// Occurs when the measurements for vertical snap points change. - /// - public event EventHandler? VerticalSnapPointsChanged - { - add => AddHandler(VerticalSnapPointsChangedEvent, value); - remove => RemoveHandler(VerticalSnapPointsChangedEvent, value); - } - bool ILogicalScrollable.IsLogicalScrollEnabled => _logicalScrollable?.IsLogicalScrollEnabled ?? false; Size ILogicalScrollable.ScrollSize => _logicalScrollable?.ScrollSize ?? default; Size ILogicalScrollable.PageScrollSize => _logicalScrollable?.PageScrollSize ?? default; Size IScrollable.Extent => _logicalScrollable?.Extent ?? default; Size IScrollable.Viewport => _logicalScrollable?.Viewport ?? default; - /// - /// Gets or sets whether the horizontal snap points for the are equidistant from each other. - /// - public bool AreHorizontalSnapPointsRegular - { - get { return GetValue(AreHorizontalSnapPointsRegularProperty); } - set { SetValue(AreHorizontalSnapPointsRegularProperty, value); } - } - - /// - /// Gets or sets whether the vertical snap points for the are equidistant from each other. - /// - public bool AreVerticalSnapPointsRegular - { - get { return GetValue(AreVerticalSnapPointsRegularProperty); } - set { SetValue(AreVerticalSnapPointsRegularProperty, value); } - } public override sealed void ApplyTemplate() { @@ -167,36 +103,14 @@ namespace Avalonia.Controls.Presenters Panel.TemplatedParent = TemplatedParent; Panel.IsItemsHost = true; - _scrollSnapPointsInfo = Panel as IScrollSnapPointsInfo; LogicalChildren.Add(Panel); VisualChildren.Add(Panel); - if (_scrollSnapPointsInfo != null) - { - _scrollSnapPointsInfo.AreVerticalSnapPointsRegular = AreVerticalSnapPointsRegular; - _scrollSnapPointsInfo.AreHorizontalSnapPointsRegular = AreHorizontalSnapPointsRegular; - } - if (Panel is VirtualizingPanel v) v.Attach(ItemsControl); else CreateSimplePanelGenerator(); - if (Panel is IScrollSnapPointsInfo scrollSnapPointsInfo) - { - scrollSnapPointsInfo.VerticalSnapPointsChanged += (s, e) => - { - e.RoutedEvent = VerticalSnapPointsChangedEvent; - RaiseEvent(e); - }; - - scrollSnapPointsInfo.HorizontalSnapPointsChanged += (s, e) => - { - e.RoutedEvent = HorizontalSnapPointsChangedEvent; - RaiseEvent(e); - }; - } - _logicalScrollable = Panel as ILogicalScrollable; if (_logicalScrollable is not null) @@ -240,16 +154,6 @@ namespace Avalonia.Controls.Presenters ResetState(); InvalidateMeasure(); } - else if(change.Property == AreHorizontalSnapPointsRegularProperty) - { - if (_scrollSnapPointsInfo != null) - _scrollSnapPointsInfo.AreHorizontalSnapPointsRegular = AreHorizontalSnapPointsRegular; - } - else if (change.Property == AreVerticalSnapPointsRegularProperty) - { - if (_scrollSnapPointsInfo != null) - _scrollSnapPointsInfo.AreVerticalSnapPointsRegular = AreVerticalSnapPointsRegular; - } } internal void Refresh() @@ -303,27 +207,5 @@ namespace Avalonia.Controls.Presenters } private void OnLogicalScrollInvalidated(object? sender, EventArgs e) => _scrollInvalidated?.Invoke(this, e); - - public IReadOnlyList GetIrregularSnapPoints(Orientation orientation, SnapPointsAlignment snapPointsAlignment) - { - if(Panel is IScrollSnapPointsInfo scrollSnapPointsInfo) - { - return scrollSnapPointsInfo.GetIrregularSnapPoints(orientation, snapPointsAlignment); - } - - return new List(); - } - - public double GetRegularSnapPoints(Orientation orientation, SnapPointsAlignment snapPointsAlignment, out double offset) - { - if (Panel is IScrollSnapPointsInfo scrollSnapPointsInfo) - { - return scrollSnapPointsInfo.GetRegularSnapPoints(orientation, snapPointsAlignment, out offset); - } - - offset = 0; - - return 0; - } } } diff --git a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs index 1c9dd79b13..701e0e4ead 100644 --- a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs +++ b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs @@ -7,6 +7,7 @@ using Avalonia.Input.GestureRecognizers; using Avalonia.Utilities; using Avalonia.VisualTree; using System.Linq; +using Avalonia.Interactivity; namespace Avalonia.Controls.Presenters { @@ -99,6 +100,7 @@ namespace Avalonia.Controls.Presenters private double _horizontalSnapPointOffset; private CompositeDisposable? _ownerSubscriptions; private ScrollViewer? _owner; + private IScrollSnapPointsInfo? _scrollSnapPointsInfo; /// /// Initializes static members of the class. @@ -570,7 +572,12 @@ namespace Avalonia.Controls.Presenters private void OnScrollGestureInertiaStartingEnded(object? sender, ScrollGestureInertiaStartingEventArgs e) { - if (Content is not IScrollSnapPointsInfo) + var scrollable = Content; + + if (Content is ItemsControl itemsControl) + scrollable = itemsControl.Presenter?.Panel; + + if (scrollable is not IScrollSnapPointsInfo) return; if (_scrollGestureSnapPoints == null) @@ -676,22 +683,6 @@ namespace Avalonia.Controls.Presenters _owner?.SetCurrentValue(OffsetProperty, change.GetNewValue()); } - else if (change.Property == ContentProperty) - { - if (change.OldValue is IScrollSnapPointsInfo oldSnapPointsInfo) - { - oldSnapPointsInfo.VerticalSnapPointsChanged -= ScrollSnapPointsInfoSnapPointsChanged; - oldSnapPointsInfo.HorizontalSnapPointsChanged += ScrollSnapPointsInfoSnapPointsChanged; - } - - if (Content is IScrollSnapPointsInfo scrollSnapPointsInfo) - { - scrollSnapPointsInfo.VerticalSnapPointsChanged += ScrollSnapPointsInfoSnapPointsChanged; - scrollSnapPointsInfo.HorizontalSnapPointsChanged += ScrollSnapPointsInfoSnapPointsChanged; - } - - UpdateSnapPoints(); - } else if (change.Property == ChildProperty) { ChildChanged(change); @@ -875,7 +866,9 @@ namespace Avalonia.Controls.Presenters private void UpdateSnapPoints() { - if (Content is IScrollSnapPointsInfo scrollSnapPointsInfo) + var scrollable = GetScrollSnapPointsInfo(Content); + + if (scrollable is IScrollSnapPointsInfo scrollSnapPointsInfo) { _areVerticalSnapPointsRegular = scrollSnapPointsInfo.AreVerticalSnapPointsRegular; _areHorizontalSnapPointsRegular = scrollSnapPointsInfo.AreHorizontalSnapPointsRegular; @@ -910,7 +903,9 @@ namespace Avalonia.Controls.Presenters private Vector SnapOffset(Vector offset) { - if(Content is not IScrollSnapPointsInfo) + var scrollable = GetScrollSnapPointsInfo(Content); + + if(scrollable is null) return offset; var diff = GetAlignedDiff(); @@ -1012,5 +1007,37 @@ namespace Avalonia.Controls.Presenters } return snapPoints[Math.Min(point, snapPoints.Count - 1)]; } + + private IScrollSnapPointsInfo? GetScrollSnapPointsInfo(object? content) + { + var scrollable = content; + + if (Content is ItemsControl itemsControl) + scrollable = itemsControl.Presenter?.Panel; + + if (Content is ItemsPresenter itemsPresenter) + scrollable = itemsPresenter.Panel; + + var snapPointsInfo = scrollable as IScrollSnapPointsInfo; + + if(snapPointsInfo != _scrollSnapPointsInfo) + { + if(_scrollSnapPointsInfo != null) + { + _scrollSnapPointsInfo.VerticalSnapPointsChanged -= ScrollSnapPointsInfoSnapPointsChanged; + _scrollSnapPointsInfo.HorizontalSnapPointsChanged -= ScrollSnapPointsInfoSnapPointsChanged; + } + + _scrollSnapPointsInfo = snapPointsInfo; + + if(_scrollSnapPointsInfo != null) + { + _scrollSnapPointsInfo.VerticalSnapPointsChanged += ScrollSnapPointsInfoSnapPointsChanged; + _scrollSnapPointsInfo.HorizontalSnapPointsChanged += ScrollSnapPointsInfoSnapPointsChanged; + } + } + + return snapPointsInfo; + } } } diff --git a/src/Avalonia.Themes.Fluent/Controls/ItemsControl.xaml b/src/Avalonia.Themes.Fluent/Controls/ItemsControl.xaml index 91f9536847..07327b530c 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ItemsControl.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ItemsControl.xaml @@ -10,8 +10,6 @@ CornerRadius="{TemplateBinding CornerRadius}" Padding="{TemplateBinding Padding}"> diff --git a/src/Avalonia.Themes.Fluent/Controls/ListBox.xaml b/src/Avalonia.Themes.Fluent/Controls/ListBox.xaml index 2dde18a523..3757f685bf 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ListBox.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ListBox.xaml @@ -40,8 +40,6 @@ AllowAutoHide="{TemplateBinding (ScrollViewer.AllowAutoHide)}" BringIntoViewOnFocusChange="{TemplateBinding (ScrollViewer.BringIntoViewOnFocusChange)}"> diff --git a/src/Avalonia.Themes.Simple/Controls/ItemsControl.xaml b/src/Avalonia.Themes.Simple/Controls/ItemsControl.xaml index ba6b37fd90..e4f4bbc4a2 100644 --- a/src/Avalonia.Themes.Simple/Controls/ItemsControl.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ItemsControl.xaml @@ -11,8 +11,6 @@ BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}"> diff --git a/src/Avalonia.Themes.Simple/Controls/ListBox.xaml b/src/Avalonia.Themes.Simple/Controls/ListBox.xaml index eeefa498a7..73c27db756 100644 --- a/src/Avalonia.Themes.Simple/Controls/ListBox.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ListBox.xaml @@ -27,8 +27,6 @@ HorizontalSnapPointsType="{TemplateBinding (ScrollViewer.HorizontalSnapPointsType)}">