/// <summary>
/// A virtual <see cref="ListView"/> class.
/// </summary>
public partial class VirtualListView : ListView
{
// ******************************************************************
// Events.
// ******************************************************************
#region Events
/// <summary>
/// Fired whenever the list needs to create a new cache item.
/// </summary>
public event EventHandler<CreateVirtualListItemEventArgs> CreateVirtualListItem;
/// <summary>
/// Fired whenever the list has cleared the internal cache.
/// </summary>
public event EventHandler ClearVirtualCache;
#endregion
// ******************************************************************
// Fields.
// ******************************************************************
#region Fields
private Dictionary<int, ListViewItem> lviCache = new Dictionary<int, ListViewItem>();
#endregion
// ******************************************************************
// Properties.
// ******************************************************************
#region Properties
/// <summary>
/// Gets or sets the virtual mode for the list.
/// </summary>
[Browsable(false)]
public new bool VirtualMode
{
get { return base.VirtualMode; }
set { base.VirtualMode = true; }
}
// ******************************************************************
/// <summary>
/// Gets and sets the size of the virtual list.
/// </summary>
public new int VirtualListSize
{
get { return base.VirtualListSize; }
set
{
// Clear the cache.
OnClearVirtualCache();
// Save the new list size (which will rebuild the cache).
base.VirtualListSize = value;
}
}
#endregion
// ******************************************************************
// Constructors.
// ******************************************************************
#region Constructors
/// <summary>
/// Creates a new instzance of the <see cref="VirtualListView"/> class.
/// </summary>
public VirtualListView()
{
InitializeComponent();
}
#endregion
// ******************************************************************
// Public methods.
// ******************************************************************
#region Public methods
/// <summary>
/// Clears the internal cache of items.
/// </summary>
public void ClearItemCache()
{
OnClearVirtualCache();
}
#endregion
// ******************************************************************
// Overrides.
// ******************************************************************
#region Overrides
/// <summary>
/// Overridden in order to setup the virtual list properties.
/// </summary>
protected override void OnCreateControl()
{
// Give the base class a chance.
base.OnCreateControl();
// Setup the virtual list properties.
base.VirtualMode = true;
}
// ******************************************************************
/// <summary>
/// Overridden in order to fetch virtual items from the cache
/// </summary>
/// <param name="e">The event arguments.</param>
protected override void OnRetrieveVirtualItem(
RetrieveVirtualItemEventArgs e
)
{
// Give the base class a chance.
base.OnRetrieveVirtualItem(e);
ListViewItem lvi;
// Check the cache first.
if (lviCache.TryGetValue(e.ItemIndex, out lvi))
{
e.Item = lvi;
return;
}
// Create an item and store it in the cache.
e.Item = OnCreateVirtualListItem(e.ItemIndex);
lviCache[e.ItemIndex] = e.Item;
}
#endregion
// ******************************************************************
// Protected methods.
// ******************************************************************
#region Protected methods
/// <summary>
/// Fires the <see cref="CreateVirtualListItem"/> event.
/// <see cref="ListVireItem"/> for the internal cache.
/// </summary>
/// <param name="index">The index of the item.</param>
/// <returns>A <see cref="ListViewItem"/> instance.</returns>
protected virtual ListViewItem OnCreateVirtualListItem(
int index
)
{
// Should we fire the event?
if (CreateVirtualListItem != null)
{
// Create the arguments.
CreateVirtualListItemEventArgs e =
new CreateVirtualListItemEventArgs(index);
// Fire the event.
CreateVirtualListItem(this, e);
// Should we validate the item?
if (e.Item != null)
{
// Loop and check each item in the list.
foreach (ListViewItem.ListViewSubItem subItem in e.Item.SubItems)
{
// If an items text is 260 characters long, add a space so it does
// not crash the program. Thanks to *** Grano Salis for the
// fix.
// https://blogs.msdn.com/cumgranosalis/archive/2006/03/18/ListViewVirtualModeBugs.aspx
if (subItem.Text.Length == 260)
subItem.Text = subItem.Text + " ";
}
}
// Return the new item.
return e.Item;
}
// Return something by default.
return new ListViewItem();
}
// ******************************************************************
/// <summary>
/// Fires the <see cref="ClearVirtualCache"/> event.
/// </summary>
protected virtual void OnClearVirtualCache()
{
// Should we fire the event?
if (ClearVirtualCache != null)
ClearVirtualCache(this, EventArgs.Empty);
// Clear the internal cache.
lviCache.Clear();
}
#endregion
}