英文:
How to keep CollectionView scrolled to bottom always in .Net MAUI
问题
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;
if (newValue is not ObservableCollection<object> collection) return;
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:
- Modify the ObservableCollection to notify on Add, or
- Modify the CollectionView to add a ScrollToBottom property, as shown below, but I still encountered failure.
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 suggestions will be thankful.
英文:
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:
- Modify the ObservableCollection to notify on Add, or
- Modify the CollectionView to add a ScrollToBottom property, as shown below, but I still encountered failure.
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.
答案1
得分: 1
CollectionView
定义了一个名为 ItemsUpdatingScrollMode
的属性,它由一个可绑定的属性支持。此属性获取或设置一个 ItemsUpdatingScrollMode
枚举值,表示在向 CollectionView
添加新项时,CollectionView
的滚动行为。ItemsUpdatingScrollMode
枚举定义了以下成员:
KeepItemsInView
:在添加新项时,保持列表中的第一项显示。KeepScrollOffset
:确保在添加新项时保持当前滚动位置不变。KeepLastItemInView
:调整滚动偏移以保持列表中的最后一项在添加新项时显示。
ItemsUpdatingScrollMode
属性的默认值是 KeepItemsInView
。因此,当向 CollectionView 添加新项时,列表中的第一项将保持显示。要确保在添加新项时显示列表中的最后一项,请将 ItemsUpdatingScrollMode
属性设置为 KeepLastItemInView
:
<CollectionView ItemsUpdatingScrollMode="KeepLastItemInView">
...
</CollectionView>
有关更多信息,请查阅文档:在添加新项时控制滚动位置。
注意:
实际上,滚动完成后可以使用 ScrollTo
方法的 position
参数指定项的确切位置。此参数接受 ScrollToPosition
枚举成员。
有关更多信息,请查阅文档:控制滚动位置。
英文:
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.
答案2
得分: 0
这在Windows平台上不起作用 - 经我测试在Android上可以工作 - 截止到.NET 7目前来看,“可能”会在.NET 8中修复 - 它已经被添加到“待办事项”中,但我没有看到任何确认是否已经进行了检查或有修复的日期。
您可以在这里查找更多信息:
[Windows] CollectionView ItemsUpdatingScrollMode property not working
#4116
英文:
This is not working for Windows platform - works on Android tested by me - currently as of .NET 7 and "probably" will be fixed by .NET 8 - it got added to the "backlog" but I don't see any confirmation about it being checked or a date to have it fixed
You can check for more information here:
[Windows] CollectionView ItemsUpdatingScrollMode property not working
#4116
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论