Click here to Skip to main content
Click here to Skip to main content

Navigational history (go back/forward) for WinForms controls

, 28 Mar 2008 CPOL
Rate this:
Please Sign up or sign in to vote.
A generic class and two ToolStripSplitButtons provide navigational history, like in web browsers.

Sample Image

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 ToolStripSplitButtons 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 LinkedListNodes. The ToolStripDropDownMenus 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
{
    // Occurs when user chose from menu or clicked button.
    public event EventHandler<HistoryEventArgs<T>> GotoItem

    // Represents the method which retrieves the menu text for an item.
    // If delegate is null, item's ToString method is used.
    public delegate string GetHistoryMenuText(T item)

    // Represents the method which retrieves the menu image for an item.
    // If delegate is null, none is used.
    public delegate Image GetHistoryMenuImage(T item)

    // forward button may be null
    // limitList == 0 for unlimited history
    public History(ToolStripSplitButton back, 
           ToolStripSplitButton forward, uint limitList)
    
    // assign new selected item on every change
    public T CurrentItem { get; set; }

    public void Clear()
    public bool AllowDuplicates { get; set; }
    
    public string GetHistoryMenuText MenuTexts { set; }
    public Image GetHistoryMenuImage MenuImages { set; }
}

// Provides data for the History<T>.GotoItem event
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 ToolStripSplitButtons 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;
    
// in form's constructor or Load eventhandler

{
    history = new History<TreeNode>(tssbBack, tssbForward, 8);
    history.GotoItem += new 
      EventHandler<HistoryEventArgs<TreeNode>>(history_GotoItem);
    
    // anonymous methods are cool

    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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

OrlandoCurioso

Germany Germany
No Biography provided

Comments and Discussions

 
Questionhow to do with multiple controls PinmemberZapss15-Apr-12 1:10 
AnswerRe: how to do with multiple controls PinmemberOrlandoCurioso15-Apr-12 11:08 
GeneralDoesn't erase items PinmemberAETCoder3-Apr-11 2:29 
GeneralRe: Doesn't erase items PinmemberAETCoder15-Apr-11 4:31 
GeneralMinor problem PinmemberRegev_Porat16-Apr-08 20:20 
GeneralRe: Minor problem PinmemberOrlandoCurioso23-Apr-08 7:36 
GeneralRe: Minor problem [modified] PinmemberFrancesco Giossi31-Jul-14 3:25 
GeneralA comment I missed PinmemberOrlandoCurioso30-Mar-08 0:51 
GeneralExcellent! PinmemberDoncp29-Mar-08 13:56 
AnswerRe: Excellent! PinmemberOrlandoCurioso29-Mar-08 23:57 
GeneralNice PinmemberPaul Conrad28-Mar-08 15:49 
GeneralSome changes I made [modified] PinmemberRobert G. Schaffrath11-Oct-06 9:06 
AnswerRe: Some changes I made PinmemberOrlandoCurioso30-Mar-08 0:34 
GeneralRe: Some changes I made Pinmemberntynhi07k109523-Apr-10 21:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.141022.2 | Last Updated 28 Mar 2008
Article Copyright 2006 by OrlandoCurioso
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid