自定义浏览器(文件资源管理器助手组件)
DevExpress WinForms套件附带了默认的WinForms文件/文件夹对话框的可皮肤对应:XtraFolderBrowserDialog、XtraOpenFileDialog和XtraSaveFileDialog。FileExplorerAssistant组件允许您在表单或UserControl中嵌入类似的功能,并构建可以导航本地存储或虚拟节点层次结构的自定义文件/文件夹浏览器。
浏览器默认文件夹
本节解释FileExplorerAssistant的核心概念,并演示如何构建类似于Windows资源管理器的标准文件/文件夹浏览器。
将FileExplorerAssistant组件放在表单或UserControl上,并调用其智能标记菜单。
点击“Add…”动作来添加所有三个浏览器组件:
- 侧边导航菜单(TreeList控件)。
- 主客户端区域(GridControl控件)。
- 地址栏(BreadCrumbEdit控件)。
所有部件都是默认的DevExpress控件,附带了FileExplorerAssistant extensions,扩展自定义控件的外观和行为,并允许这些控件与其父组件FileExplorerAssistant通信。
扩展包括:
- GridControl扩展(GridControl)
- TreeList扩展(TreeList)
- Breadcrumb编辑扩展(breadcrumbed)
- 预览面板扩展(PanelControl)
当单击“Add…”智能标签菜单操作时,组件会创建相应的control-extension对。如果需要,您可以单击“Edit Extensions”智能标签菜单操作来创建独立的扩展,并将它们绑定到表单或UserControl上的控件。
TreeList扩展
TreeList扩展具有指定顶级节点列表的RootNodes集合。最初,这个集合只有一个节点——EnvironmentSpecialFolderNode,它允许用户浏览一个:桌面、我的文档、程序文件、字体和其他。该节点的初始值为“Desktop”,允许用户浏览当前PC的整个本地存储。
您可以修改此集合来添加其他节点:
PathNode指向单个本地存储文件夹或驱动器,此对象的路径存储在节点的path属性中。
C#:
// Scan for all partitions System.IO.DriveInfo[] driveList = System.IO.DriveInfo.GetDrives(); foreach (var drive in driveList) { // Select only logical fixed partitions if (drive.DriveType == System.IO.DriveType.Fixed && drive.IsReady) // Add each drive as a root node treeListExtension1.RootNodes.Add(new PathNode(drive.RootDirectory.ToString())); }
点击复制
VB.NET:
' Scan for all partitions Dim driveList() As System.IO.DriveInfo = System.IO.DriveInfo.GetDrives() For Each drive In driveList ' Select only logical fixed partitions If drive.DriveType = System.IO.DriveType.Fixed AndAlso drive.IsReady Then ' Add each drive as a root node treeListExtension1.RootNodes.Add(New PathNode(drive.RootDirectory.ToString())) End If Next drive
点击复制
GuidNode允许您添加具有 的特殊文件夹。
C#:
// Add the "Network" special folder GuidNode nodeNetwork = new GuidNode(new Guid("d20beec4-5ca8-4905-ae3b-bf251ea09b53")); nodeNetwork.AutoExpand = false; treeListExtension1.RootNodes.Add(nodeNetwork);
点击复制
VB.NET:
' Add the "Network" special folder Dim nodeNetwork As New GuidNode(New Guid("d20beec4-5ca8-4905-ae3b-bf251ea09b53")) nodeNetwork.AutoExpand = False treeListExtension1.RootNodes.Add(nodeNetwork)
点击复制
VirtualFolderNode和VirtualItemNode为自定义节点,您可以指定它们的标题和图像,VirtualFolderNodes可以用子节点填充,使用这些节点创建本地存储中不存在的自定义项。
GridControl扩展
GridControl扩展的两个核心设置是:
- ViewMode——允许您在8种资源管理器样式(磁贴、内容、大图标等)之间进行选择。
- CurrentPath——当前浏览的目录。
BreadcrumbEdit扩展
CurrentPath是当前浏览的目录。
预览窗格扩展
集成预览窗格,有了它,用户可以在打开实际文件之前预览与office相关的文档(如DOCX、XLSX、CSV)、pdf、HTML文件、文本文件和图像。
连接扩展
扩展之间不进行通信。例如,如果用户在TreeList中选择一个节点,则Data Grid不会反映此导航,需要根据自定义文件夹资源管理器的结构实现扩展之间的通信。
导航绑定
“navigation binding”是DevExpress.XtraDialogs.NavigationBinding类的一个对象,这些对象有两个属性:
- Source——指定跟踪其导航的控件。
- Target ——指定应复制源控件导航的控件。
当存储在FileExplorerAssistant.NavigationBindings集合中时,导航绑定将导航操作从该FileExplorerAssistant组件拥有的一个扩展传输到另一个扩展。
您可以在设计时添加导航绑定(在Visual Studio属性网格中单击“NavigationBindings”属性旁边的省略号按钮)或在代码中添加。在设计时,Collection Editor对话框检查是否设置了Target和Source属性,并突出显示缺少这两个设置中的任何一个的绑定。
您也可以在代码中编辑导航绑定:
C#:
NavigationBinding nbGridToBreadcrumb = new NavigationBinding(); nbGridToBreadcrumb.Source = gridControlExtension1; nbGridToBreadcrumb.Target = breadCrumbExtension1; fileExplorerAssistant1.NavigationBindings.Add(nbGridToBreadcrumb);
点击复制
VB.NET:
Dim nbGridToBreadcrumb As New NavigationBinding() nbGridToBreadcrumb.Source = gridControlExtension1 nbGridToBreadcrumb.Target = breadCrumbExtension1 fileExplorerAssistant1.NavigationBindings.Add(nbGridToBreadcrumb)
点击复制
下面的例子演示了如何将预览面板扩展绑定到网格控制扩展:
C#:
var gridExtension = assistant.Attach(grid, x => { x.CurrentPath = initialPath; }); var previewExtension = assistant.Attach(panel); assistant.NavigationBindings.Add(new NavigationBinding() { Source = gridExtension, Target = previewExtension });
点击复制
VB.NET:
Dim gridExtension = assistant.Attach(grid, Sub(x) x.CurrentPath = initialPath) Dim previewExtension = assistant.Attach(panel) assistant.NavigationBindings.Add(New NavigationBinding() With {.Source = gridExtension, .Target = previewExtension})
点击复制
导航事件
连接扩展的另一种方法是处理每个FileExplorerAssistant扩展可用的CurrentItemChanged事件,每当用户在控件中选择不同的项时,都会触发此事件。处理CurrentItemChanged,如果您需要实现一个定制的扩展通信逻辑,而这个逻辑不能用导航绑定实现。
C#:
private void treeListExtension1_CurrentItemChanged(object sender, CurrentItemChangedEventArgs e) { // Update Data Grid and Breadcrumb when the Tree List selection changes gridControlExtension1.SetCurrentItem(e.CurrentItem); breadCrumbExtension1.SetCurrentItem(e.CurrentItem); }
点击复制
VB.NET:
Private Sub treeListExtension1_CurrentItemChanged(ByVal sender As Object, ByVal e As CurrentItemChangedEventArgs) ' Update Data Grid and Breadcrumb when the Tree List selection changes gridControlExtension1.SetCurrentItem(e.CurrentItem) breadCrumbExtension1.SetCurrentItem(e.CurrentItem) End Sub
点击复制
导航和编辑按钮
FileExplorerAssistant扩展公开了一个API,允许您管理文件和文件夹。本节将演示如何使用该API来实现类似于DevExpress演示中“Two-Panel File Manager”中的操作按钮。
- DoDefaultAction ——在选定的文件夹中导航,或者在与文件扩展名相关联的默认程序中打开选定的文件(记事本用于.txt文件,照片用于.png文件,等等)。
- Rename ——重命名所选文件或文件夹。
- CopySelectedItem和 MoveSelectedItem ——将选定的文件或文件夹复制或移动到方法参数指定的位置,在下面的代码中,所选文件被复制到另一个网格的当前打开的文件夹中。
C#:
gridControlExtension1.CopySelectedItem(gridControlExtension2.CurrentFolder);
点击复制
VB.NET:
gridControlExtension1.CopySelectedItem(gridControlExtension2.CurrentFolder)
点击复制
- CreateNewFolder ——在当前浏览的文件夹中创建一个新目录。
- GoBack、GoForward、 GoUp——导航方法。
C#:
// Navigate to the parent folder gridControlExtension1.GoUp();
点击复制
VB.NET:
' Navigate to the parent folder gridControlExtension1.GoUp()
点击复制
- 以“Can”开头的属性返回是否可以对当前文件夹或文件执行相应的操作。例如,如果用户浏览SpecialEnvironmentFolder.Desktop,它们无法导航到父文件夹(group方法不可用),并且canoup属性返回false。
C#:
// Set the availability of a button that calls the Rename method btnRename.Enabled = gridControlExtension1.CanRename;
点击复制
VB.NET:
' Set the availability of a button that calls the Rename method btnRename.Enabled = gridControlExtension1.CanRename
点击复制
- SetCurrentPath and SetCurrentSpecialFolder——允许您浏览特定的文件夹或特殊的Windows文件夹。
C#:
breadCrumbExtension1.SetCurrentSpecialFolder(Environment.SpecialFolder.CommonStartMenu); // or breadCrumbExtension1.SetCurrentPath( Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu));
点击复制
VB.NET:
breadCrumbExtension1.SetCurrentSpecialFolder(Environment.SpecialFolder.CommonStartMenu) ' or breadCrumbExtension1.SetCurrentPath(Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu))
点击复制
自定义层次结构
FileExplorerAssistant组件允许您创建解决方案,不仅可以浏览本地存储上的文件夹,还可以浏览虚拟(自定义)层次结构。
要为Tree List控件创建自定义层次结构,请使用VirtualFolderNode和VirtualItemNode实例填充控件相关扩展的RootNodes集合。
VirtualFolderNode类对象充当“folders”,这些对象具有Nodes集合,您可以使用该集合用子文件夹或项填充它们。
C#:
VirtualFolderNode rootNode = new VirtualFolderNode("Root Node"); VirtualFolderNode childNode = new VirtualFolderNode("Child Node 1"); rootNode.ImageOptions.SvgImage = svgImageCollection1[0]; childNode.ImageOptions.SvgImage = svgImageCollection1[1]; // ... // Add more child nodes rootNode.Nodes.Add(childNode); treeListExtension1.RootNodes.Add(rootNode);
点击复制
VB.NET:
Dim rootNode As VirtualFolderNode = New VirtualFolderNode("Root Node") Dim childNode As VirtualFolderNode = New VirtualFolderNode("Child Node 1") rootNode.ImageOptions.SvgImage = svgImageCollection1(0) childNode.ImageOptions.SvgImage = svgImageCollection1(1) ' ... ' Add more child nodes rootNode.Nodes.Add(childNode) treeListExtension1.RootNodes.Add(rootNode)
点击复制
VirtualItemNode类对象作为“files”,这些对象不能嵌入其他文件夹或项,也不会显示在树列表中(类似于本地存储文件)。
C#:
VirtualFolderNode rootNode = new VirtualFolderNode("Root Node"); rootNode.Nodes.Add(new VirtualFolderNode("Child Node 1")); ((VirtualFolderNode)rootNode.Nodes[0]).Nodes.Add(item1);
点击复制
VB.NET:
Dim rootNode As New VirtualFolderNode("Root Node") rootNode.Nodes.Add(New VirtualFolderNode("Child Node 1")) CType(rootNode.Nodes(0), VirtualFolderNode).Nodes.Add(item1)
点击复制
组合虚拟“folder”和“file”对象,根据需要创建自定义层次结构。
自定义预览
下面的例子演示了如何预览SVG文件:
C#:
using DevExpress.Dialogs.Core.Items; using DevExpress.Utils.Svg; using DevExpress.XtraEditors; using DevExpress.XtraEditors.Base.Controls.Preview; using DevExpress.XtraEditors.Controls; using System.Windows.Forms; var gridExtension = assistant.Attach(grid, x => { x.CurrentPath = initialPath; x.FilterString = "Svg files (*.svg)|*.svg"; }); var previewExtension = assistant.Attach(panel, x => { x.CustomizePreview += (s, e) => { if(e.Item.Extension.ToLower() == ".svg") e.CustomPreviewHandler = new SvgPreviewHandler(); }; }); assistant.NavigationBindings.Add(new NavigationBinding() { Source = gridExtension, Target = previewExtension }); //... public class SvgPreviewHandler : WinPreviewHandlerBase { SvgImage svgImage; public override bool Load(string file, ShellItem shellItem) { base.Load(file, shellItem); bool loaded = false; if(shellItem.Extension.ToLower() == ".svg") { try { this.svgImage = SvgImage.FromFile(file); loaded = true; } catch { } } return loaded; } public override Control CreatePreviewControl() { var picEdit = new PictureEdit(); picEdit.SvgImage = svgImage; picEdit.Enabled = false; picEdit.BorderStyle = BorderStyles.NoBorder; picEdit.Properties.SizeMode = PictureSizeMode.Squeeze; picEdit.Properties.UseDisabledStatePainter = false; return picEdit; } }
点击复制
VB.NET:
Imports DevExpress.Dialogs.Core.Items Imports DevExpress.Utils.Svg Imports DevExpress.XtraEditors Imports DevExpress.XtraEditors.Base.Controls.Preview Imports DevExpress.XtraEditors.Controls Imports System.Windows.Forms Private gridExtension = assistant.Attach(grid, Sub(x) x.CurrentPath = initialPath x.FilterString = "Svg files (*.svg)|*.svg" End Sub) Private previewExtension = assistant.Attach(panel, Sub(x) AddHandler x.CustomizePreview, Sub(s, e) If e.Item.Extension.ToLower() = ".svg" Then e.CustomPreviewHandler = New SvgPreviewHandler() End If End Sub End Sub) assistant.NavigationBindings.Add(New NavigationBinding() With {.Source = gridExtension, .Target = previewExtension}) ' ... Public Class SvgPreviewHandler Inherits WinPreviewHandlerBase Private svgImage As SvgImage Public Overrides Function Load(ByVal file As String, ByVal shellItem As ShellItem) As Boolean MyBase.Load(file, shellItem) Dim loaded As Boolean = False If shellItem.Extension.ToLower() = ".svg" Then Try Me.svgImage = SvgImage.FromFile(file) loaded = True Catch End Try End If Return loaded End Function Public Overrides Function CreatePreviewControl() As Control Dim picEdit = New PictureEdit() picEdit.SvgImage = svgImage picEdit.Enabled = False picEdit.BorderStyle = BorderStyles.NoBorder picEdit.Properties.SizeMode = PictureSizeMode.Squeeze picEdit.Properties.UseDisabledStatePainter = False Return picEdit End Function End Class
点击复制
自定义上下文菜单
在WinForms文件资源管理器助手组件中处理以下事件来自定义上下文菜单(添加新命令,隐藏/禁用命令等):
- ContextMenuShowing
- BeforeExecuteItemCommand
C#:
assistant.Attach(grid, x => { x.CurrentPath = initialPath; string customCommandName = "custom"; x.ContextMenuShowing += (s, e) => { e.MenuItems.AddCommand("Custom command", customCommandName); }; x.BeforeExecuteItemCommand += (s, e) => { if(e.CommandName == customCommandName) { XtraMessageBox.Show("Custom command executed"); e.Cancel = true; } }; });
点击复制
VB.NET:
assistant.Attach(grid, Sub(x) x.CurrentPath = initialPath Dim customCommandName As String = "custom" AddHandler x.ContextMenuShowing, Sub(s, e) e.MenuItems.AddCommand("Custom command", customCommandName) End Sub AddHandler x.BeforeExecuteItemCommand, Sub(s, e) If e.CommandName = customCommandName Then XtraMessageBox.Show("Custom command executed") e.Cancel = True End If End Sub End Sub)
点击复制