// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Windows.Controls;
using ILSpy.Debugger.Services;
namespace ILSpy.Debugger.Tooltips
{
///
/// ItemsControl wrapper that takes VirtualizingIEnumerable as source,
/// and adds additional items from the source to underlying ItemsControl when scrolled to bottom.
///
public class LazyItemsControl
{
private ItemsControl itemsControl;
private int initialItemsCount;
///
/// Creates new instance of LazyItemsControl.
///
/// ItemsControl to wrap and add items to it when scrolled to bottom.
/// Number of items to be initially displayed in wrapped ItemsControl.
public LazyItemsControl(ItemsControl wrappedItemsControl, int initialItemsCount)
{
if (wrappedItemsControl == null)
throw new ArgumentNullException("wrappedItemsControl");
this.initialItemsCount = initialItemsCount;
this.itemsControl = wrappedItemsControl;
this.itemsControl.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(handleScroll));
}
private ScrollViewer scrollViewerCached;
public ScrollViewer ScrollViewer
{
get
{
if (this.scrollViewerCached == null)
this.scrollViewerCached = this.itemsControl.GetScrollViewer();
return this.scrollViewerCached;
}
}
public bool IsScrolledToStart
{
get
{
if (ScrollViewer == null) // Visual tree not initialized yet
return false;
return ScrollViewer.VerticalOffset == 0;
}
}
public bool IsScrolledToEnd
{
get
{
if (itemsSourceTotalCount == null) {
// not scrolled to end of IEnumerable yet
return false;
}
// already scrolled to end of IEnumerable
int totalItems = itemsSourceTotalCount.Value;
return (ScrollViewer.VerticalOffset >= totalItems - ScrollViewer.ViewportHeight);
}
}
private int? itemsSourceTotalCount = null;
/// Items count of underlying IEnumerable. Null until scrolled to the end of IEnumerable.
public int? ItemsSourceTotalCount
{
get
{
return this.itemsSourceTotalCount;
}
}
private VirtualizingIEnumerable itemsSource;
/// The collection that underlying ItemsControl sees.
public VirtualizingIEnumerable ItemsSource
{
get { return itemsSource; }
set
{
this.itemsSource = value;
addNextItems(this.itemsSource, initialItemsCount);
this.itemsControl.ItemsSource = value;
}
}
private void addNextItems(VirtualizingIEnumerable sourceToAdd, int nItems)
{
sourceToAdd.AddNextItems(nItems);
if (!sourceToAdd.HasNext) {
// all items from IEnumerable have been added
this.itemsSourceTotalCount = sourceToAdd.Count;
}
}
private void handleScroll(object sender, ScrollChangedEventArgs e)
{
if (e.VerticalChange > 0) {
// scrolled to bottom
if (e.VerticalOffset >= this.itemsSource.Count - e.ViewportHeight) {
addNextItems(this.itemsSource, (int)e.VerticalChange);
}
}
}
}
}