65.9K
CodeProject 正在变化。 阅读更多。
Home

最近使用 (MRU) 组件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.38/5 (4投票s)

2004年11月5日

5分钟阅读

viewsIcon

112977

downloadIcon

661

一个用 C# 编写的最近使用 (MRU) 组件。

Sample Image - MRUHandler1.jpg

引言

为了学习 C#,我开始重新开发一个我之前用 Java 编写的应用程序。我很快意识到,和许多人一样,.NET 框架中没有内置最近使用功能。

MRUHandler 组件显示一个最近使用 (MRU) 菜单列表。可以在同一个应用程序中使用多个 MRUHanlder 组件而不会发生冲突。例如,上面的图片展示了支持文件 MRU 历史和 URL MRU 历史的演示程序。同样,它也适用于多文档界面 (MDI) 应用程序的上下文。

背景

在 CodeProject 搜索后,我找到了两篇参考文章:Joe Woodury 的 C# 中的最近使用 (MRU) 菜单类 和 Alex Farber 的 向 Windows 应用程序添加最近使用文件 (MRU) 列表。不幸的是,这些文章都不符合我的要求,因为我正在寻找一种允许我“插入”MRU 功能的方法。阅读 Philip Davis 的文章 状态消息的扩展接口后,我决定尝试将此功能开发为自定义组件。

MRUHandler 概述

属性

属性只能在设计器或框架初始化期间设置。我未能找到一种方法将属性从设计器序列化到运行时,就像在 Visual Basic 6.0 中可以做的那样。我最终实现的是 ISupportInitialize 接口。该接口允许 MRUHandler 捕获初始化开始和结束,并设置一个初始化标志。如果有人知道如何让框架做到这一点,我将非常感激。

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();
    }
}

然后,如果 _isInitializing 标志未设置或组件不在设计模式下,每个属性都会抛出异常。

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

可用属性

  • DisplayLength:显示 MRU 条目文件名时的最大长度。
  • MaxFiles:MRU 历史中要维护的最大文件数。
  • MRUItem:菜单项,它是历史列表的占位符(当样式为 Inline 时)或父菜单项(当样式为 Popup 时)。
  • MRUStyle:枚举类型,指示 MRU 历史是以内联方式显示还是作为弹出菜单显示。
  • ShowShortItem:布尔值,指示显示名称是否应被压缩。如果此值为 false,则忽略 DisplayLength 属性。
  • StorageName:为用于持久化 MRU 历史的文件或注册表项提供名称。如果 StorageType 属性为 FileIsolatedStorage,则使用产品名称 (Application.ProductName) 和此属性生成完整的文件名,文件扩展名为 .mru。如果 StorageTypeRegistry,则此属性用于在应用程序用户数据注册表 (Application.UserAppDataRegistry) 下创建一个子项。
  • StorageStyle:枚举属性,用于确定用于保存 MRU 历史信息的持久化存储的位置。值为:
    • IsolatedStorage:MRU 历史使用 .NET 隔离存储设施进行存储。
    • File:MRU 历史存储在文件系统中,位于可执行文件路径 (Application.ExecutablePath) 下。
    • Registry:MRU 历史使用 Win32 注册表进行存储。值将被添加到 StorageName 属性指定的项下。

公共方法

  • AddRecentlyUsedFile:
    显示 MRU 条目文件名时的最大长度。

事件

  • MRUItemClicked:显示 MRU 条目文件名时的最大长度。

使用 MRUHandler 组件

一旦 MRUHandler 安装在 Visual Studio 中,为应用程序添加 MRU 支持就像将组件拖到主窗口上,然后选择要用作 MRU 历史占位符的菜单项一样简单。最好为该菜单项起一个有意义的名称,以便在列表中查找。

选择菜单项后,创建 MRUItemClicked 处理程序。

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

MRUItemClickedEventArgs 有一个 File 属性,其中包含要从 MRU 历史中打开的文件路径名。在演示程序中,DoFileOpen 读取文件并打开子窗口以显示内容。

最后一步是提供一个机制,允许应用程序告诉 MRUHandler 要跟踪和显示哪些文件路径。这可以通过调用 AddRecentlyUsedFile 方法并传入刚打开的文件路径名来完成。

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);
}

关注点

设置 DataSet 的修饰符

在将 MRU 持久化到文件系统时,我使用了 DataSet 对象来定义 XML 架构,并执行文件系统和 MRUHandler 之间的实际信息传输。我发现 Visual Studio 提供的默认实现将生成类的访问修饰符设置为 public。结果是 MRUListFile 会作为组件出现在工具栏上。花了一段时间,但通过转到类视图并选择 MRUListFile.xsd 的属性,我成功地更改了生成类的访问修饰符。然后我能够将其更改为 internal,这有效地在设计器中隐藏了该类。

版本构建

我发现每次重新构建包含 MRUHandler 的应用程序时,在使用值为 RegistryStorageType 时,MRU 历史都会重置为空。事实证明,Application.UserAppDataRegistry 指向一个包含 Visual Studio 生成的版本号的应用程序子项。如果这是一个问题,修改代码以从项中删除版本号将非常简单。

© . All rights reserved.