0

所以,我有一个listview,我希望它创建一个项目时滚动到该项目(底部)。因为我使用的是MVVM,所以我发现了一个非常好的解释,说明如何创建一个从listview向下滚动的新控件。问题是this answer (the third)指的是6年前的WPF。 我正在制作UWP应用程序,因此我复制了代码并尝试将其格式化为我的需要。下面的代码不会给出任何错误或异常,但是它会加载“ChatListView”,因为我称它为完美,然后什么都不做。与原始代码相比,这些评论只是经过了一点编辑。UWP自定义ListView向下滚动

我该怎么办?先谢谢你!

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); 
    } 
} 

回答

4

如果你想创建可以使用ItemsStackPanelItemsUpdatingScrollMode特定属性以KeepLastItemInView值滚动到最新的项聊天应用。

用法:

<ListView> 
    <ListView.ItemsPanel> 
     <ItemsPanelTemplate> 
      <ItemsStackPanel ItemsUpdatingScrollMode="KeepLastItemInView" /> 
     </ItemsPanelTemplate> 
    </ListView.ItemsPanel> 
</ListView> 

注:KeepLastItemInView枚举成员在14393 SDK进行了介绍。

相关链接: https://docs.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.Controls.ItemsStackPanel#properties_

+2

这甚至超过了我是问......它不仅向下滚动,当你在名单上添加的东西,而且如果你是不是在观看最后一项(例如,如果你想查看以前的消息),它不会向下滚动。完善!!! – KonKarapas

1

接受的答案是相当不错的。但是我有一件事情是不会做的(至少如果我简单地复制并粘贴上面的XAML):如果用户在添加新项目时离开该页面,它不会执行其预期的滚动,然后他们导航到页面。

对于我只好挂到

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); 
}