清单:获取下一个/上一个n项

时间:2015-06-16 12:23:28

标签: c# wpf linq list listview

我想知道使用LINQ是否可以编写一个简短的算法来实现它。

这就是我所说的。

我们假设您有List 500件。现在,出于性能原因,您不希望将此列表绑定到ListView。相反,您只想显示其中的一部分,而当用户滚动时,您会加载下一个之前的项目。

考虑以下方法:public List<MyItemType> GetPartOfList(bool next, int quantity);

您将如何完成,以便它返回包含某个数量项目的Listbool参数告知您是否需要下一个上一个项目。

当然,要避免使用OutOfBounds Exception,您必须返回一个列表,其中包含较少的项目,但这样可以。

是否已经有这样的算法,因为我不想重建车轮?谢谢!

目前,这就是我所做的:

    private int _currentIndexBeg = 0; // required to know where the current portion of the list starts
    private int _currentIndexEnd = 0; // required to know where the current portion of the list stops
    public ObservableCollection<T> GetPartOfConversation( bool less, int quantity )
    {
         if( quantity < 0 )
             throw new ArgumentException( "quantity", "quantity MUST NOT be NEGATIVE!" );

         if (quantity > _originalList.Count)
         {
             _currentIndexBeg = 0;
             _currentIndexEnd = _originalList.Count;
             return _originalList; // list is small enough
         }

         if (_currentIndexBeg == 0 && _currentIndexEnd == 0) // first time call
         {
             _currentIndexBeg = 0;
             _currentIndexEnd = quantity;
             return new ObserableCollection<T>(_originalList.GetRange(0, quantity); // safe, no risk of exception, already handled before
         }
         else
         {
             // now onto the fun part
             if (less) //meaning we want the PREVIOUS "quantity" items
             {
                if( _currentIndexBeg == 0 ) // which means top in the list, no more items
                    return null; //if null, it means there is no other items to be displayed into the ListView. Requires a null check, that's still OK.
                if (_currentIndexBeg - quantity < 0) // alright, we want the n previous items. But if there are previous items but not as much as we would want we could either return what remains, 
                              // or what remains plus what already exists to make sure we return a List of quantity elements
                {
                      // TODO
                    return null; // TODO
                }
                 // here means that there is at least (equal or more) quantity elements that remains and can be displayed
                 // TODO
             }
             else //meaning we want the NEXT "quantity" items
             {
                 if( _currentIndexEnd == _originalList.Count ) // which means bottom of the list, no more items
                    return null; //if null, it means there is no other items to be displayed into the ListView. Requires a null check, that's still OK.
                 if (_currentIndexEnd + quantity > originalList.Count) // aright, we want the n next items. But if there are indeed next available items, but not as much as we would want
                                       // we could return what remains (less than quantity) or what remains + what already exists
                 {
                     int remain = originalList.Count - _currentIndexEnd - 1; // minus 1 because zero based indexation
                     return new ObserableCollection<T>(_originalList.GetRange(_currentIndexEnd , remain);
                     // OR
                     return new ObserableCollection<T>(_originalList.GetRange(_currentIndexEnd - (quantity - remain) , quantity); // to match the requested quantity
                 }
                 // here means that there is at least (equal or more) quantity elements that remains and can be displayed
                 // TODO
             }
     }
 }

随着我的进步,我会更新代码,但如果我做了一些完全错误的事情,我想帮忙。谢谢!

[UPDATE]

更多说明:

  1. 我的ListView显示两个用户之间的对话;
  2. 我的内部List包含代表&#34;聊天的自定义项目 气泡&#34; ;
  3. 会话可以随着消息的添加而增长;
  4. 每次添加消息时,我都想显示它,所以 ListView自动滚动到最后一个条目(最后一条消息) 使用ScrollIntoView(); 我无法使用此处所述的Virtualisationhttps://stackoverflow.com/a/30765631/3535408

2 个答案:

答案 0 :(得分:1)

你有没有探究过Virtualization?这是内置功能,通过仅渲染可见内容来实现您所描述的内容。您仍然会绑定整个集合,但框架将处理渲染逻辑。您只需将VirtualizingStackPanel.IsVirtualizing属性设置为true即可。根据您的代码判断,您已将整个列表保留在内存中,因此通过LINQ进行批处理只会增加开销。有关其他详细信息,请参阅以下链接。

https://msdn.microsoft.com/en-us/library/cc716879(v=vs.110).aspx

How to enable UI virtualization in Standard WPF ListView

<强>更新

无法拥有VirtualizationCanContentScroll='False'Is it possible to implement smooth scroll in a WPF listview?)。以下是一些想到的解决方法:

  • 获取最新的N项,但是 允许用户延迟加载旧项目;这是一种采用的技术 许多聊天应用程序。但是,当用户加载更多项目时, 您将体验到您试图避免的性能损失。 通过这种方法,您只能对用户进行对冲 偶尔会关心较旧的对话。

  • ListView中的项目限制为a 可管理的号码,并允许用户访问不同的页面 查看扩展的聊天记录。

  • 如果你有房地产,你也可以增加高度 ListView和/或减少要显示的项目的高度 一次更多的项目,这应该有效地减慢你的滚动速度。 (另)

答案 1 :(得分:0)

在linq中,最好的方法是使用Skip和Take方法。

Iterable

在您的代码中,您只需在用户滚动时知道“页面”编号。