I wonder if with LINQ it is possible to write a short algorithm to achieve that.
Here is what I am talking about.
Let's say you have a List
of 500 items. Now, for performance reasons, you do not want to bind this list to your ListView
. Rather, you'd want to only display a portion of it and as the user scroll, you load the next or previous items.
Consider the following method : public List<MyItemType> GetPartOfList(bool next, int quantity);
How would you complete so that it returns you a List
containing a certain quantity of item. The bool
parameter tells whether you want the next or previous set of items.
Of course, to avoid OutOfBounds Exception
, you will have to return a list with less items that asked but that's OK.
Is there already such an alogorithm available as I would not want to rebuild the wheel ? Thanks !
For now, here is what I did :
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
}
}
}
I will update the code as I progress but I'd like to have help if I am doing something utterly wrong. Thanks !
[UPDATE]
For more clarification :
- My
ListView
displays a conversation between two users ; - My internal
List
contains custom-maded item representating a "chat bubble" ; - The conversation can grow as messages are added ;
- Each time a message is added, I want to display it, so the
ListView
scrolls automatically to the last entry (last message) usingScrollIntoView()
; I cannot useVirtualisation
as described here : https://stackoverflow.com/a/30765631/3535408