Reputation: 366
So, I have a listview and I want it whenever an item is created to scroll to that item (bottom). Because I am using MVVM I found really nice explanation on how to make a new control that inherits from listview that scrolls down. The problem is that this answer (the third) is referring to WPF 6 years ago. I am making a UWP app, so I copied the code and tried to format it to my needs. The following code doesn't give any error or exception but instead it loads the "ChatListView" as I call it perfectly and then does nothing. The comments are only a bit edited compared to the original code.
What can I do ? Thank you in advance!
public class ChatListView : ListView
{
//Define the AutoScroll property. If enabled, causes the ListBox to scroll to
//the last item whenever a new item is added.
public static readonly DependencyProperty AutoScrollProperty =
DependencyProperty.Register(
"AutoScroll",
typeof(Boolean),
typeof(ChatListView),
new PropertyMetadata(
true, //Default value.
new PropertyChangedCallback(AutoScroll_PropertyChanged)));
//Gets or sets whether or not the list should scroll to the last item
//when a new item is added.
public bool AutoScroll
{
get { return (bool)GetValue(AutoScrollProperty); }
set { SetValue(AutoScrollProperty, value); }
}
//Event handler for when the AutoScroll property is changed.
//This delegates the call to SubscribeToAutoScroll_ItemsCollectionChanged().
//d = The DependencyObject whose property was changed.</param>
//e = Change event args.</param>
private static void AutoScroll_PropertyChanged(
DependencyObject d, DependencyPropertyChangedEventArgs e)
{
SubscribeToAutoScroll_ItemsCollectionChanged(
(ChatListView)d,
(bool)e.NewValue);
}
//Subscribes to the list items' collection changed event if AutoScroll is enabled.
//Otherwise, it unsubscribes from that event.
//For this to work, the underlying list must implement INotifyCollectionChanged.
//
//(This function was only creative for brevity)
//listBox = The list box containing the items collection.
//subscribe = Subscribe to the collection changed event?
private static void SubscribeToAutoScroll_ItemsCollectionChanged(
ChatListView listView, bool subscribe)
{
INotifyCollectionChanged notifyCollection =
listView as INotifyCollectionChanged;
if (notifyCollection != null)
{
if (subscribe)
{
//AutoScroll is turned on, subscribe to collection changed events.
notifyCollection.CollectionChanged +=
listView.AutoScroll_ItemsCollectionChanged;
}
else
{
//AutoScroll is turned off, unsubscribe from collection changed events.
notifyCollection.CollectionChanged -=
listView.AutoScroll_ItemsCollectionChanged;
}
}
}
//Event handler called only when the ItemCollection changes
//and if AutoScroll is enabled.
//sender = The ItemCollection.
//e = Change event args.
private void AutoScroll_ItemsCollectionChanged(
object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
int count = Items.Count;
ScrollIntoView(Items[count - 1]);
}
}
//Constructor a new ChatListView.
public ChatListView()
{
//Subscribe to the AutoScroll property's items collection
//changed handler by default if AutoScroll is enabled by default.
SubscribeToAutoScroll_ItemsCollectionChanged(
this, (bool)AutoScrollProperty.GetMetadata(typeof(ChatListView)).DefaultValue);
}
}
Upvotes: 6
Views: 1799
Reputation: 8506
The accepted answer is pretty nice. However I there is one thing it won't do (at least if I simply copy and paste the above XAML): it won't do its intended scrolling if, say, the user was away from that page while new items were added, and then they navigated to the page.
For that I had to hook into
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (MyListView.Items.Count == 0)
return;
object lastItem = MyListView.Items[MyListView.Items.Count - 1];
MyListView.ScrollIntoView(lastItem);
}
Upvotes: 2
Reputation: 1565
If you want to create a chat application you can use the ItemsStackPanel
's ItemsUpdatingScrollMode
particular property to KeepLastItemInView
value to scroll to the latest item.
Usage:
<ListView>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel ItemsUpdatingScrollMode="KeepLastItemInView" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
Note: KeepLastItemInView
enum member was introduced in the 14393 SDK.
Related link: https://learn.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.Controls.ItemsStackPanel#properties_
Upvotes: 16