Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Most Recently Used (MRU) Component

0.00/5 (No votes)
5 Nov 2004 1  
A Most Recently Used component written in C#.

Sample Image - MRUHandler1.jpg

Introduction

In an effort to learn C#, I started to redevelop an application program that I had written in Java. I quickly realized, like many others, that there was no Most Recently Used functionality built into the .NET framework.

The MRUHandler component displays a most recently used (MRU) menu list. Multiple MRUHanlder components can be used in the same application without colliding. For example, the image above depicts the demo program supporting an MRU history for files and a MRU history for viewed URLs. As well, it will work within the context of a Multiple Document Interface (MDI) application.

Background

After searching CodeProject, I found two reference articles: Joe Woodury's Most Recently Used (MRU) Menu class in C# and Alex Farber's Add Most Recently Used Files (MRU) List to Windows Applications. Unfortunately, neither of these appealed to me, as I was looking for an approach that would allow me to "plug-in" the MRU functionality. After reading Philip Davis� article Extended Interface for Status Message, I decided to try developing this functionality as a custom Component.

MRUHandler Overview

Properties

The properties can only be set from the Designer or during the framework initialization. I was unsuccessful in finding a way to serialize the properties from the designer into the runtime, as you were able to do in Visual Basic 6.0. What I ended up doing was implementing the ISupportInitialize interface. This interface allows the MRUHandler to trap the start and end of the initialization and set an initializing flag. If anyone knows how to get the framework to do this, I would sure appreciate the input.

public void BeginInit() {_isInitializing = true;}
public void EndInit() {
    _isInitializing = false;
    if (!DesignMode) {
        if (_mruItem == null) {
            throw new Exception("The property 'MruItem' item cannot be set to null");
        }
        RebuildMenu();
    }
}

Each of the properties then throws an exception if the _isInitializing flag is not set or the component is not in Design mode.

public MenuItem MruItem {
    get{ return _mruItem;  }
    set{ 
        if (!DesignMode && !_isInitializing) {
            throw new Exception("The 'MruItem' can be only set in Design Mode");
        }
        _mruItem = value; 
    }
}

Available Properties

  • DisplayLength: The maximum length of the MRU entry file name when displayed.
  • MaxFiles: The maximum number of files to be maintained in the MRU History.
  • MRUItem: The menu item that is the place holder for the history list (when the style is Inline) or the parent menu item (when the style is Popup).
  • MRUStyle: Enumerated type to indicate if the MRU history should be displayed inline or as a popup menu.
  • ShowShortItem: Boolean value to indicate whether the display name should be compressed. If this is false, then the DisplayLength property is ignored.
  • StorageName: Provides a name for the file or registry key that is used to persist the MRU history. If the StorageType property is File or IsolatedStorage, the complete file name is generated using the product name (Application.ProductName) and this property, and the extension of the file is .mru. If the StorageType is Registry, this property is used to create a subkey under the application user data registry (Application.UserAppDataRegistry).
  • StorageStyle: Enumerated property to determine the location of the persistent storage used to save the MRU history information. Values are:
    • IsolatedStorage: The MRU history is stored using the .NET Isolated Storage facilities.
    • File: The MRU history is stored on the file system in the executable path (Application.ExecutablePath).
    • Registry: The MRU history is stored using the Win32 Registry. The values are added to the key specified by the StorageName property.

Public Methods

  • AddRecentlyUsedFile:
    The maximum length of the MRU entry file name when displayed.

Events

  • MRUItemClicked: The maximum length of the MRU entry file name when displayed.

Using the MRUHandler Component

Once the MRUHandler is installed in Visual Studio, adding MRU support to your application is as simple as dragging the component on to the main window and choosing which menu item is to be used as the MRU history placeholder. It is a good idea to have named this menu item something meaningful in order to assist in finding it in the list.

Once you have chosen the menu item, then create the MRUItemClicked handler.

private void OnMRUItemClicked(object sender, 
        MostRecentlyUsedHandler.MRUItemClickedEventArgs e) {
    DoFileOpen(e.File);
}

The MRUItemClickedEventArgs has a property File that contains the path name of the file that corresponds to be opened from the MRU history. In the demo program, DoFileOpen reads the file and opens the child window to display the contents.

The last step is to provide the mechanism that allows the application to tell the MRUHandler which file paths to keep track of and display. This is done by calling the AddRecentlyUsedFile method and passing the file path name that was just opened.

private void DoFileOpen(string fileName) {
    FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
    Child form = new Child(fs);
    form.MdiParent = this;
    form.Show();
    mruHandler1.AddRecentlyUsedFile(fileName);
}

Points of Interest

Setting the modifier of the DataSet

When persisting the MRU to the file system, I had used a DataSet object to define an XML schema and do the actual transfer of information between the file system and the MRUHandler. I found that the default implementation provided by Visual Studio sets the access modifier of the generated class to public. The result was that MRUListFile would show up on the Toolbar as a component. It took a while, but I was able to change the access modifier of the generated class by going to the class view and selecting the properties of MRUListFile.xsd. I was then able to change the modifier to internal, which effectively hid this class in the designer.

Build Versioning

I found that each time I rebuilt the application that contains the MRUHandler, the MRU history would be reset to empty when I was using a StorageType with a value of Registry. It turns out that the Application.UserAppDataRegistry refers to an application subkey that contains the Visual Studio generated version number. If this is a problem, it would be quite simple to modify the code to remove the version number from the key.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here