Click here to Skip to main content
15,881,709 members
Articles / Programming Languages / C#

Add Most Recently Used Files (MRU) List to Windows Applications

Rate me:
Please Sign up or sign in to vote.
5.00/5 (8 votes)
26 Nov 2012CPOL3 min read 50.1K   1.9K   26   8
A .NET4.0 alternative for "Add Most Recently Used Files (MRU) List to Windows Applications"

Image 1

Introduction

I've written applications in the past in which users need to open files and have found that they usually re-open the same files over and over. So instead of forcing them to browse and open the same file over and over again, I decided to create an MRUManager, to make things easier.

Background

It uses the Windows Registry to store the paths of the recently opened files, so if you're not familiar with the registry, Wikipedia would be a good place to start. As a reference, use Microsoft's documentation of the C# class Microsoft.Win32.Registry if you're unsure about the registry manipulation methods.

Using the Code

You can use the MRUManager class right away (at your own risk, of course) without having to modify the code. There are only a few requirements.

C#
void myOwnRecentFileGotClicked_handler(void obj, EventArgs evt)  

This method will be called when the user clicks on one of the recent items.

  1. Using Visual Studio, create a ToolStripMenuItem to be used as the parent menu item of the recent files list. Don't put sub-menu items in this one as they will be removed by the MRUManager.
  2. Create a method with this prototype.
  3. Optional: create a method that has the same parameters as the previous one. This will be called after a user clicks 'Clear list'.

Once you have those, simply create a new instance of the MRUManager class, like so:

C#
private MRUManager mruManager;
 
private void Form1_Load(object sender, EventArgs e)
{
    this.mruManager = new MRUManager(
    //the menu item that will contain the recent files
    this.recentFilesToolStripMenuItem, 
 
    //the name of your program
    "myProgram",
    
    //the function that will be called when a recent file gets clicked.
    this.myOwn_recentFileGotClicked_handler, 
    
    //an optional function to call when the user clears the list of recent items
    this.myOwn_recentFilesGotCleared_handler);
}

Afterwards, there are two public methods that can be called:

C#
public void AddRecentFile(string fileNameWithFullPath)
public void RemoveRecentFile(string fileNameWithFullPath) 

Examples of their usage:

C#
private void openToolStripMenuItem_Click(object obj, EventArgs evt)
{
    FileDialog openFileDlg = new OpenFileDialog();
    openFileDlg.InitialDirectory = Environment.CurrentDirectory;
    if(openFileDlg.ShowDialog() != DialogResult.OK)
        return;
    string openedFile = openFileDlg.FileName;
    
    //Now give it to the MRUManager
    this.mruManager.AddRecentFile(openedFile);
 
    //do something with the file here
    MessageBox.Show("Through the 'Open' menu item, you opened: " + openedFile);
}
C#
private void myOwn_recentFileGotClicked_handler(object obj, EventArgs evt)
{
    string fName = (obj as ToolStripItem).Text;
    if (!File.Exists(fName))
    {
        if (MessageBox.Show(string.Format("{0} doesn't exist. Remove from recent " + 
                 "workspaces?", fName), "File not found", 
                 MessageBoxButtons.YesNo) == DialogResult.Yes)
            this.mruManager.RemoveRecentFile(fName);
        return;
    }
    
    //do something with the file here
    MessageBox.Show(string.Format("Through the 'Recent Files' menu item, you opened: {0}", fName));
}
  1. If a user opens (or even saves) a file
  2. When the user clicks on a recent file, but it doesn't exist

Inside the Class

Below is an overall view of the class:

C#
public class MRUManager
{
    private string NameOfProgram;
    private string SubKeyName;
    private ToolStripMenuItem ParentMenuItem;
    private Action<object, EventArgs> OnRecentFileClick;
    private Action<object, EventArgs> OnClearRecentFilesClick;
 
    private void _onClearRecentFiles_Click(object obj, EventArgs evt)
    private void _refreshRecentFilesMenu()
    
    public void AddRecentFile(string fileNameWithFullPath)
    public void RemoveRecentFile(string fileNameWithFullPath)
    
    public MRUManager(
        ToolStripMenuItem parentMenuItem,
        string nameOfProgram,
        Action<object, EventArgs> onRecentFileClick,
        Action<object, EventArgs> onClearRecentFilesClick = null
    )
}

There are two private methods that do some of the work for the class: _refreshRecentFilesMenu() and _onClearRecentFiles_Click().

When a new MRUManager object is instantiated, the constructor checks for invalid parameters. If there are any, it throws a new ArgumentException. It then calls _refreshRecentFilesMenu() to update the list, in case there were any entries previously stored in the registry.

The registry key that the class stores recent files under is "HKEY_CURRENT_USER\SOFTWARE\{program name that you supplied}\MRU". It stores this string in a private member, SubKeyName.

Whenever you call AddRecentFile(), it creates a new value under that key. Value names are numerical and go from 0 to as many as you add. It then calls _refreshRecentFilesMenu().

Whenever you call RemoveRecentFile(), it searches for a value under SubKeyName that contains the file name that you pass in and deletes it. It then calls _refreshRecentFilesMenu().

_refreshRecentFilesMenu() calls {ToolStripMenuItem that you supplied}.DropDownItems.Clear() and then repopulates it with all the values in the registry. Each recent file menu item that it adds gets passed an EventHandler that points to the function that you supplied. It then adds two items: a separator and 'Clear list' menu item, which, when clicked, runs the private method _onClearRecentFiles_Click().

_onClearRecentFiles_Click() does three things: clears the registry of recent files, clears the menu item and calls the function that the user may have optionally specified.

Simplified versions of _refreshRecentFilesMenu() and _onClearRecentFiles_Click() are shown below:

C#
private void _refreshRecentFilesMenu()
{
    string s;
    ToolStripItem tSI;
    RegistryKey rK = Registry.CurrentUser.OpenSubKey(this.SubKeyName, false);
 
    this.ParentMenuItem.DropDownItems.Clear();
    string[] valueNames = rK.GetValueNames();
    foreach (string valueName in valueNames)
    {
        s = rK.GetValue(valueName, null) as string;
        if (s == null)
            continue;
        tSI = this.ParentMenuItem.DropDownItems.Add(s);
        tSI.Click += new EventHandler(this.OnRecentFileClick);
    }
 
    if (this.ParentMenuItem.DropDownItems.Count == 0)
    {
    this.ParentMenuItem.Enabled = false;
        return;
    }
 
    this.ParentMenuItem.DropDownItems.Add("-");
    tSI = this.ParentMenuItem.DropDownItems.Add("Clear list");
    tSI.Click += new EventHandler(this._onClearRecentFiles_Click);
    this.ParentMenuItem.Enabled = true;
}  
C#
private void _onClearRecentFiles_Click_SIMPLIFIED(object obj, EventArgs evt)
{
    RegistryKey rK = Registry.CurrentUser.OpenSubKey(this.SubKeyName, true);
    if (rK == null)
        return;
    string[] values = rK.GetValueNames();
    foreach (string valueName in values)
        rK.DeleteValue(valueName, true);
    rK.Close();
    this.ParentMenuItem.DropDownItems.Clear();
    this.ParentMenuItem.Enabled = false;
    
    if (OnClearRecentFilesClick != null)
        this.OnClearRecentFilesClick(obj, evt);
}

Deviations from the Original Article

Although the MRUManager class in this article was written from scratch, it bears a resemblance to the original article's implementation. For example, it still uses the registry to store file paths and the GUI interface it creates is much like the original. I decided to make my MRUManager more minimalistic, by not including things like 'maxNumberOfFiles' or 'maxDisplayLength', yet still functional enough to use right away.

History

  • June 19, 2012 - Article created
  • June 20, 2012 - Article changed as an alternative
  • November 20, 2012 - Bug fix: RemoveRecentFile() not properly removing files from list

License

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


Written By
Software Developer
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralVisualstudio ItemTemplate Pin
Klaus Ruttkowski1-Jul-21 6:21
Klaus Ruttkowski1-Jul-21 6:21 
QuestionMany Thanks Pin
Mohammad Nasser20-Jan-16 0:52
professionalMohammad Nasser20-Jan-16 0:52 
QuestionRemoveRecentFile() method Pin
jfilhoul20-Nov-12 1:49
jfilhoul20-Nov-12 1:49 
AnswerRe: RemoveRecentFile() method Pin
Adib Saad25-Nov-12 8:09
Adib Saad25-Nov-12 8:09 
QuestionVB.Net Port Pin
Tim Bacon19-Aug-12 3:58
Tim Bacon19-Aug-12 3:58 
GeneralMy vote of 5 Pin
karthikin30-Jul-12 1:24
karthikin30-Jul-12 1:24 
QuestionMRu items Pin
marasal25-Jun-12 7:01
marasal25-Jun-12 7:01 
AnswerRe: MRu items Pin
Adib Saad26-Jun-12 5:31
Adib Saad26-Jun-12 5:31 

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

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