I want to create a Log window using CollectionView. Whenever a new item is added, it should automatically scroll to the bottom. I attempted to implement this functionality using a behavior for easy code portability. Here's how I wrote the behavior:
namespace Behaviors;
public class ScrollToBottomBehavior
{
public static readonly BindableProperty DataSourceProperty =
BindableProperty.CreateAttached("DataSource",
typeof(object),
typeof(ScrollToBottomBehavior),
null,
BindingMode.TwoWay,
propertyChanged: OnDataSourceChanged);
public static int GetDataSource(BindableObject view) => (int)view.GetValue(DataSourceProperty);
public static void SetDataSource(BindableObject view, int value) => view.SetValue(DataSourceProperty, value);
private static void OnDataSourceChanged(BindableObject sender, object oldValue, object newValue)
{
if (sender is not CollectionView view) return;
//ObservableCollection<object> collection = newValue as ObservableCollection<object>;
if (newValue is not ObservableCollection<object> collection) return;
//view?.ScrollTo(collection.LastOrDefault(), null, ScrollToPosition.End);
view?.ScrollTo(collection.Count - 1, position: ScrollToPosition.End);
}
}
However, I failed because the Add method of ObservableCollection does not trigger the PropertyChanged event.
I also tried manually setting the SelectedItem to the last item of the ObservableCollection every time an item was added, but this didn't make the CollectionView scroll to the bottom automatically.
I have a couple of ideas:
internal class CollectionViewExtended : CollectionView
{
public static readonly BindableProperty ScrollToButtomProperty =
BindableProperty.Create(nameof(ScrollToButtom), typeof(bool), typeof(CollectionViewExtended), false);
public bool ScrollToButtom
{
get => (bool)GetValue(ScrollToButtomProperty);
set => SetValue(ScrollToButtomProperty, value);
}
protected override void OnChildAdded(Element child)
{
base.OnChildAdded(child);
if (ScrollToButtom)
{
ScrollTo(child, position: ScrollToPosition.End, animate: true);
}
}
}
Any sugguestions will be thankful.
CollectionView
defines a ItemsUpdatingScrollMode
property, which is backed by a bindable property. This property gets or sets a ItemsUpdatingScrollMode
enumeration value that represents the scrolling behavior of the CollectionView
when new items are added to it. The ItemsUpdatingScrollMode
enumeration defines the following members:
KeepItemsInView
keeps the first item in the list displayed when new
items are added.KeepScrollOffset
ensures that the current scroll position is
maintained when new items are added.KeepLastItemInView
adjusts the scroll offset to keep the last item in
the list displayed when new items are added.The default value of the ItemsUpdatingScrollMode
property is KeepItemsInView
. Therefore, when new items are added to a CollectionView the first item in the list will remain displayed. To ensure that the last item in the list is displayed when new items are added, set the ItemsUpdatingScrollMode
property to KeepLastItemInView
:
<CollectionView ItemsUpdatingScrollMode="KeepLastItemInView">
...
</CollectionView>
For more information, check document: Control scroll position when new items are added.
Note:
In fact, the exact position of the item after the scroll has completed can be specified with the position argument of the ScrollTo
methods. This argument accepts a ScrollToPosition
enumeration member.
For more information, check document: Control scroll position.