最近使用 (MRU) 组件






4.38/5 (4投票s)
2004年11月5日
5分钟阅读

112977

661
一个用 C# 编写的最近使用 (MRU) 组件。
引言
为了学习 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
属性为File
或IsolatedStorage
,则使用产品名称 (Application.ProductName
) 和此属性生成完整的文件名,文件扩展名为 .mru。如果StorageType
为Registry
,则此属性用于在应用程序用户数据注册表 (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
的应用程序时,在使用值为 Registry
的 StorageType
时,MRU 历史都会重置为空。事实证明,Application.UserAppDataRegistry
指向一个包含 Visual Studio 生成的版本号的应用程序子项。如果这是一个问题,修改代码以从项中删除版本号将非常简单。