在开发应用程序时,经常需要添加最近使用的文件(MRU)功能,以提高用户体验。这可以通过两种方式实现:传统的菜单和类似于Visual Studio起始页面的GUI控件。在进行一些搜索后,决定创建自己的MRU项目,考虑到灵活性和逻辑的可重用性。
让向介绍OpenMRUSuite——一个用于将“MRU文件”功能添加到.NET应用程序的项目。该项目的主要特点是极大的灵活性。为了实现这一点,该套件由两个程序集组成:
OpenMRU.Core
(负责“逻辑”部分,不依赖于GUI框架)和OpenMRU.WinForm
(用于WinForm应用程序的GUI控件,使用OpenMRU.Core
作为“后端”)。所有这些程序集都可以通过NuGet获取。同时,可以在GitHub上查看该项目。
如果只想使用GUI控件而不想深入了解实现细节,请查看下面的代码片段。(假设已经引用了OpenMru.Core
和OpenMRU.WinForm
库,一个名为Form1
的表单,一个名为mruItemsControl1
的MRUItemsControl控件,一个名为ButtonOpen
的按钮,以及两个名为recentFilesToolStripMenuItem
和recentcustomToolStripMenuItem
的ToolStripMenuItem控件):
public partial class Form1 : Form
{
// 链接到管理器
private readonly MRUManager manager;
public Form1()
{
InitializeComponent();
// 使用OpenMRU.Core中的默认基于xml的存储创建IMRUItemStorage实现
MRUItemFileStorage storage = new MRUItemFileStorage("demo_mru_storage.xml");
// 从OpenMRU.Core创建默认管理器
manager = new MRUManager();
// 使用存储初始化管理器
manager.Initialize(storage);
// 订阅“项目选择”事件
manager.MRUItemSelected += Manager_MRUItemSelected;
// 使用创建的管理器和默认(英文)本地化初始化GUI控件
mruItemsControl1.Initialize(manager, new MRUGuiLocalization());
// 初始化菜单项
MRUItemsMenu itemsMenu = new MRUItemsMenu();
itemsMenu.Initialize(manager, new MRUGuiLocalization());
itemsMenu.AttachToMenu(recentFilesToolStripMenuItem);
// 初始化菜单项 - 自定义外观
MRUItemsMenu itemsMenu2 = new MRUItemsMenu();
itemsMenu2.Initialize(manager, new MRUGuiLocalization());
itemsMenu2.AttachToMenu(recentcustomToolStripMenuItem, "%FileName% - [%Path%] - [%AccessDate%]");
}
private void Manager_MRUItemSelected(string path)
{
MessageBox.Show("Select file from MRU: " + path);
}
// 处理打开文件事件
private void ButtonOpen_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
{
string path = ofd.FileName;
// 将用户选择的文件添加到管理器(开始跟踪并在GUI上显示)
manager.AddFile(path);
}
}
}
从上面的代码中,可以看到,所有应该对MRU项目选择事件做出反应的逻辑或应该向MRU项目添加新文件的逻辑,都必须引用IMRUManager实现(在这个例子中,它是MRUManager - OpenMRU.Core的默认实现)。因此,它使逻辑独立于GUI实现 - 只需注入用于GUI初始化的相同IMRUManager实例,就可以开始了!
OpenMRU.Core
作为“MRU文件”功能的基础(或某种“后端”)。它包含用于管理MRU项目的接口及其默认实现,GUI部分的接口,处理这些GUI界面的逻辑以及MRU项目模型。
OpenMRU.Core
分为两个逻辑部分:“Common”(包含不涉及GUI的接口/类)和“View”(包含“视图”的接口,管理“视图”的逻辑,本地化类)。
通用部分提供以下接口/类:
正如此时所注意到的,可以提供自己的IMRUItemStorage实现(例如,实现可能使用数据库存储MRU项目),甚至IMRUManager(如果想提供额外的功能)。
视图部分提供以下接口/类:
public class MRUMessages
{
// 项目删除的确认消息
public string AllowDeleteItem { get; set; }
// 清除所有项目的确认消息
public string AllowClearList { get; set; }
public MRUMessages()
{
AllowDeleteItem = "This action will delete item from list. Continue?";
AllowClearList = "This action will delete all items from list. Continue?";
}
}
通过将本地化的值设置为本地化类实例的相应属性,可以为MRU GUI控件提供自己的本地化!可以使用任何本地化数据源(.resx文件,ini文件等)来获取本地化类实例属性的值。
MRUGuiLogic - 驱动MRU项目“视图”的逻辑(IMRUItemsView的实现)。 MRUGuiLogic类使用给定的本地化对象将IMRUItemsView和IMRUManager实现绑定在一起。它处理MRU项目的选定/筛选/更新,使得“视图”实现非常简单。
让看看“视图”接口:
public interface IMRUItemView
{
event Action PinItemRequested;
event Action DeleteItemRequested;
event Action ItemSelected;
void Initialize(MRUItem item, MRUGuiItemLocalization localization);
void Initialize(MRUItem item, MRUGuiItemLocalization localization, string imagePathForItem);
}
public interface IMRUItemsView
{
event Action ClearMRUItemsRequested;
bool IsActionAllowed(string actionDescription);
void Initialize(IMRUManager manager, MRUGuiLocalization localization);
void ShowMRUItems(List containers);
List ItemViews { get; }
}
如所见,“视图”的要求相当简单。 IMRUItemView实现应在用户尝试固定项目,删除或选择它时触发相应的事件。还应支持使用给定的MRUItem模型,本地化和项目图像路径进行初始化(即,将它们用作渲染相应视觉元素的数据源)。 IMRUItemsView实现应在用户尝试清除MRU项目时触发相应的事件,应能够询问用户关于某些操作的允许性(例如,显示对话框),渲染MRU项目容器并公开“项目视图”列表作为IMRUItemView列表。
因此,可以创建自己的GUI控件,实现IMRUItemView和IMRUItemsView,专注于视觉呈现,将逻辑处理留给OpenMRU.Core。
或者,如果正在开发WinForm应用程序,可以使用OpenMRU.WinForm - 包含MRU项目显示组件的程序包:作为WinForm GUI控件(类似于Visual Studio起始窗口上的控件)和传统菜单。这些控件实现IMRUItemView和IMRUItemsView,并依赖于OpenMRU.Core。请参见快速入门部分的使用示例。请注意,某些MRU项目的图像将按以下顺序确定:如果客户端指定了图像文件,则将使用此图像;否则,系统将尝试从与MRU项目关联的文件中获取图像。如果上述所有方法都失败,则将使用默认图像(来自嵌入式资源文件)。
// 表示外观的字符串
// 可用占位符:
// %FileName% - 仅文件名(不带路径)
// %Path% - 文件路径(不包括文件名)
// %FullFileName% - 文件路径 + 文件名
// %AccessDate% - MRU项目的最后访问日期
// 默认值:%FullFileName%