Introduction
With controls that present large quantities of distinct items, providing a history of user's selections might enhance user pleasure. Especially, since (s)he would be accustomed to this feature from the web browser experience. This article presents a History<T>
class, which is generic for the selected item, and works in conjunction with one or two ToolStripSplitButton
s to provide the feature.
Background
The class handles the functionality of the buttons, their appearance is not its responsibility. Updating the class with new selections is accomplished by assigning the current selection to the CurrentItem
property inside an appropriate SelectionChanged
event handler of the historized control. Internally, history is tracked by a generic LinkedList
, with the selected items as LinkedListNode
s. The ToolStripDropDownMenu
s are filled dynamically on their respective Opening
events. If an exact history is feasible, the default filtering of duplicates can be turned off. No fancy coding to further mention it here.
Public Interface
With the provided comments, I hope that the usage would be self-explanatory:
public sealed class History<T> : IDisposable where T : class
{
public event EventHandler<HistoryEventArgs<T>> GotoItem
public delegate string GetHistoryMenuText(T item)
public delegate Image GetHistoryMenuImage(T item)
public History(ToolStripSplitButton back,
ToolStripSplitButton forward, uint limitList)
public T CurrentItem { get; set; }
public void Clear()
public bool AllowDuplicates { get; set; }
public string GetHistoryMenuText MenuTexts { set; }
public Image GetHistoryMenuImage MenuImages { set; }
}
public class HistoryEventArgs<T> : EventArgs
{
public HistoryEventArgs(T item)
public T Item { get; }
}
Using the Code
The provided demo shows the most simplistic use with a ListBox
. You might copy the ToolStripSplitButton
s to your own project. Here is a slightly elaborated example for a TreeView
, with support of menu images:
private TreeView treeView;
private ToolStripSplitButton tssbBack;
private ToolStripSplitButton tssbForward;
private History<TreeNode> history;
{
history = new History<TreeNode>(tssbBack, tssbForward, 8);
history.GotoItem += new
EventHandler<HistoryEventArgs<TreeNode>>(history_GotoItem);
history.MenuTexts = delegate(TreeNode node) { return node.Text; };
history.MenuImages = delegate(TreeNode node) { return
treeView.ImageList != null && !string.IsNullOrEmpty(node.ImageKey)
? treeView.ImageList.Images[node.ImageKey] : null; };
}
private void treeView_AfterSelect(object sender, TreeViewEventArgs e)
{
history.CurrentItem = treeView.SelectedNode;
}
private void history_GotoItem(object sender,
HistoryEventArgs<TreeNode> e)
{
treeView.SelectedNode = e.Item;
}
protected override void Dispose(bool disposing)
{
if (disposing && history != null)
{
history.Dispose();
}
base.Dispose(disposing);
}
Last, but not the least, the item T
could be a custom class, exposing additional properties, like an absolute address that allows reloading of items which are not contained anymore in the current view.
Points of Interest
- Encapsulating buttons and classes by deriving from a
ToolStripControlHost
control. - Your comments, suggestions, and votes.
History
- February 2006: coded.
- April 2006: published.
- March 2008: Class constraint added and implements IDisposable.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.