Mvvm 要向下滚动的UWP自定义列表视图

Mvvm 要向下滚动的UWP自定义列表视图,mvvm,uwp,custom-controls,observablecollection,dependency-properties,Mvvm,Uwp,Custom Controls,Observablecollection,Dependency Properties,因此,我有一个listview,每当创建一个项目时,我都希望它滚动到该项目(底部)。因为我使用的是MVVM,所以我找到了关于如何创建从向下滚动的listview继承的新控件的非常好的解释。问题是,这是指6年前的WPF。 我正在制作一个UWP应用程序,所以我复制了代码并试图根据我的需要格式化它。下面的代码没有给出任何错误或异常,而是加载了我称之为“ChatListView”的“ChatListView”,然后什么也不做。与原始代码相比,注释只经过一点编辑 我能做什么?提前谢谢你 public cl

因此,我有一个listview,每当创建一个项目时,我都希望它滚动到该项目(底部)。因为我使用的是MVVM,所以我找到了关于如何创建从向下滚动的listview继承的新控件的非常好的解释。问题是,这是指6年前的WPF。 我正在制作一个UWP应用程序,所以我复制了代码并试图根据我的需要格式化它。下面的代码没有给出任何错误或异常,而是加载了我称之为“ChatListView”的“ChatListView”,然后什么也不做。与原始代码相比,注释只经过一点编辑

我能做什么?提前谢谢你

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);
    }
}
公共类ChatListView:ListView
{
//定义AutoScroll属性。如果启用,将导致列表框滚动到
//添加新项时的最后一项。
公共静态只读从属属性AutoScrollProperty=
从属属性。寄存器(
“自动滚动”,
类型(布尔),
类型(聊天列表视图),
新属性元数据(
true,//默认值。
新属性更改回调(AutoScroll_属性更改));
//获取或设置列表是否应滚动到最后一项
//添加新项目时。
公共图书馆自动阅览室
{
get{return(bool)GetValue(AutoScrollProperty);}
set{SetValue(AutoScrollProperty,value);}
}
//更改AutoScroll属性时的事件处理程序。
//这将委托对SubscribeToAutoScroll\u ItemsCollectionChanged()的调用。
//d=属性已更改的DependencyObject。
//e=更改事件参数。
私有静态无效自动滚动属性已更改(
DependencyObject d,DependencyPropertyChangedEventArgs e)
{
SubscribeToAutoScroll\u项目集合已更改(
(ChatListView)d,
(bool)e.NewValue);
}
//如果启用了AutoScroll,则订阅列表项的集合更改事件。
//否则,它将取消该活动的订阅。
//要使其工作,基础列表必须实现INotifyCollectionChanged。
//
//(此功能仅为简洁而具有创造性)
//listBox=包含items集合的列表框。
//订阅=订阅集合更改事件?
私有静态无效SubscribeToAutoScroll\u ItemsCollectionChanged(
ChatListView列表视图,bool订阅)
{
INotifyCollectionChanged notifyCollection=
listView作为INotifyCollectionChanged;
if(notifyCollection!=null)
{
如果(订阅)
{
//AutoScroll已打开,订阅集合更改事件。
notifyCollection.CollectionChanged+=
listView.AutoScroll_项目集合已更改;
}
其他的
{
//AutoScroll已关闭,取消订阅集合更改事件。
notifyCollection.CollectionChanged-=
listView.AutoScroll_项目集合已更改;
}
}
}
//仅当ItemCollection更改时才调用事件处理程序
//如果启用了自动滚动。
//sender=项目集合。
//e=更改事件参数。
私有无效自动滚动项集合已更改(
对象发送方,NotifyCollectionChangedEventArgs(e)
{
if(e.Action==NotifyCollectionChangedAction.Add)
{
int count=项目数;
ScrollIntoView(项目[计数-1]);
}
}
//构造函数创建一个新的ChatListView。
公共聊天列表视图()
{
//订阅AutoScroll属性的items集合
//如果默认情况下启用了AutoScroll,则默认情况下已更改处理程序。
SubscribeToAutoScroll\u项目集合已更改(
这个(bool)AutoScrollProperty.GetMetadata(typeof(ChatListView)).DefaultValue);
}
}

如果要创建聊天应用程序,可以使用
ItemsStackPanel
ItemsUpdatingScrollMode
特定属性的
KeepLastItemInView
值滚动至最新项目

用法:

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

注意:
KeepLastItemInView
enum成员是在14393 SDK中引入的

相关链接:
公认的答案很好。但是,我认为有一件事它不会做(至少如果我只是复制并粘贴上面的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);
}

这比我要求的还要多。。。它不仅在您在列表中添加内容时向下滚动,而且如果您不想查看最后一项(例如,如果您想查看以前的消息),它也不会向下滚动。完美的正是我需要的!非常感谢。