自定義瀏覽器(文件資源管理器助手組件)
DevExpress WinForms套件附帶了默認(rèn)的WinForms文件/文件夾對(duì)話(huà)框的可皮膚對(duì)應(yīng):XtraFolderBrowserDialog、XtraOpenFileDialog和XtraSaveFileDialog。FileExplorerAssistant組件允許您在表單或UserControl中嵌入類(lèi)似的功能,并構(gòu)建可以導(dǎo)航本地存儲(chǔ)或虛擬節(jié)點(diǎn)層次結(jié)構(gòu)的自定義文件/文件夾瀏覽器。
瀏覽器默認(rèn)文件夾
本節(jié)解釋FileExplorerAssistant的核心概念,并演示如何構(gòu)建類(lèi)似于Windows資源管理器的標(biāo)準(zhǔn)文件/文件夾瀏覽器。
將FileExplorerAssistant組件放在表單或UserControl上,并調(diào)用其智能標(biāo)記菜單。
點(diǎn)擊“Add…”動(dòng)作來(lái)添加所有三個(gè)瀏覽器組件:
- 側(cè)邊導(dǎo)航菜單(TreeList控件)。
- 主客戶(hù)端區(qū)域(GridControl控件)。
- 地址欄(BreadCrumbEdit控件)。
所有部件都是默認(rèn)的DevExpress控件,附帶了FileExplorerAssistant extensions,擴(kuò)展自定義控件的外觀和行為,并允許這些控件與其父組件FileExplorerAssistant通信。
擴(kuò)展包括:
- GridControl擴(kuò)展(GridControl)
- TreeList擴(kuò)展(TreeList)
- Breadcrumb編輯擴(kuò)展(breadcrumbed)
- 預(yù)覽面板擴(kuò)展(PanelControl)
當(dāng)單擊“Add…”智能標(biāo)簽菜單操作時(shí),組件會(huì)創(chuàng)建相應(yīng)的control-extension對(duì)。如果需要,您可以單擊“Edit Extensions”智能標(biāo)簽菜單操作來(lái)創(chuàng)建獨(dú)立的擴(kuò)展,并將它們綁定到表單或UserControl上的控件。
TreeList擴(kuò)展
TreeList擴(kuò)展具有指定頂級(jí)節(jié)點(diǎn)列表的RootNodes集合。最初,這個(gè)集合只有一個(gè)節(jié)點(diǎn)——EnvironmentSpecialFolderNode,它允許用戶(hù)瀏覽一個(gè)特殊的Windows文件夾:桌面、我的文檔、程序文件、字體和其他。該節(jié)點(diǎn)的初始值為“Desktop”,允許用戶(hù)瀏覽當(dāng)前PC的整個(gè)本地存儲(chǔ)。
您可以修改此集合來(lái)添加其他節(jié)點(diǎn):
PathNode指向單個(gè)本地存儲(chǔ)文件夾或驅(qū)動(dòng)器,此對(duì)象的路徑存儲(chǔ)在節(jié)點(diǎn)的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())); }
點(diǎn)擊復(fù)制
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
點(diǎn)擊復(fù)制
GuidNode允許您添加具有 GUIDs 的特殊文件夾。
C#:
// Add the "Network" special folder GuidNode nodeNetwork = new GuidNode(new Guid("d20beec4-5ca8-4905-ae3b-bf251ea09b53")); nodeNetwork.AutoExpand = false; treeListExtension1.RootNodes.Add(nodeNetwork);
點(diǎn)擊復(fù)制
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)
點(diǎn)擊復(fù)制
VirtualFolderNode和VirtualItemNode為自定義節(jié)點(diǎn),您可以指定它們的標(biāo)題和圖像,VirtualFolderNodes可以用子節(jié)點(diǎn)填充,使用這些節(jié)點(diǎn)創(chuàng)建本地存儲(chǔ)中不存在的自定義項(xiàng)。
GridControl擴(kuò)展
GridControl擴(kuò)展的兩個(gè)核心設(shè)置是:
- ViewMode——允許您在8種資源管理器樣式(磁貼、內(nèi)容、大圖標(biāo)等)之間進(jìn)行選擇。
- CurrentPath——當(dāng)前瀏覽的目錄。
BreadcrumbEdit擴(kuò)展
CurrentPath是當(dāng)前瀏覽的目錄。
預(yù)覽窗格擴(kuò)展
集成預(yù)覽窗格,有了它,用戶(hù)可以在打開(kāi)實(shí)際文件之前預(yù)覽與office相關(guān)的文檔(如DOCX、XLSX、CSV)、pdf、HTML文件、文本文件和圖像。
連接擴(kuò)展
擴(kuò)展之間不進(jìn)行通信。例如,如果用戶(hù)在TreeList中選擇一個(gè)節(jié)點(diǎn),則Data Grid不會(huì)反映此導(dǎo)航,需要根據(jù)自定義文件夾資源管理器的結(jié)構(gòu)實(shí)現(xiàn)擴(kuò)展之間的通信。
導(dǎo)航綁定
“navigation binding”是DevExpress.XtraDialogs.NavigationBinding類(lèi)的一個(gè)對(duì)象,這些對(duì)象有兩個(gè)屬性:
- Source——指定跟蹤其導(dǎo)航的控件。
- Target ——指定應(yīng)復(fù)制源控件導(dǎo)航的控件。
當(dāng)存儲(chǔ)在FileExplorerAssistant.NavigationBindings集合中時(shí),導(dǎo)航綁定將導(dǎo)航操作從該FileExplorerAssistant組件擁有的一個(gè)擴(kuò)展傳輸?shù)搅硪粋€(gè)擴(kuò)展。
您可以在設(shè)計(jì)時(shí)添加導(dǎo)航綁定(在Visual Studio屬性網(wǎng)格中單擊“NavigationBindings”屬性旁邊的省略號(hào)按鈕)或在代碼中添加。在設(shè)計(jì)時(shí),Collection Editor對(duì)話(huà)框檢查是否設(shè)置了Target和Source屬性,并突出顯示缺少這兩個(gè)設(shè)置中的任何一個(gè)的綁定。
您也可以在代碼中編輯導(dǎo)航綁定:
C#:
NavigationBinding nbGridToBreadcrumb = new NavigationBinding(); nbGridToBreadcrumb.Source = gridControlExtension1; nbGridToBreadcrumb.Target = breadCrumbExtension1; fileExplorerAssistant1.NavigationBindings.Add(nbGridToBreadcrumb);
點(diǎn)擊復(fù)制
VB.NET:
Dim nbGridToBreadcrumb As New NavigationBinding() nbGridToBreadcrumb.Source = gridControlExtension1 nbGridToBreadcrumb.Target = breadCrumbExtension1 fileExplorerAssistant1.NavigationBindings.Add(nbGridToBreadcrumb)
點(diǎn)擊復(fù)制
下面的例子演示了如何將預(yù)覽面板擴(kuò)展綁定到網(wǎng)格控制擴(kuò)展:
C#:
var gridExtension = assistant.Attach(grid, x => { x.CurrentPath = initialPath; }); var previewExtension = assistant.Attach(panel); assistant.NavigationBindings.Add(new NavigationBinding() { Source = gridExtension, Target = previewExtension });
點(diǎn)擊復(fù)制
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})
點(diǎn)擊復(fù)制
導(dǎo)航事件
連接擴(kuò)展的另一種方法是處理每個(gè)FileExplorerAssistant擴(kuò)展可用的CurrentItemChanged事件,每當(dāng)用戶(hù)在控件中選擇不同的項(xiàng)時(shí),都會(huì)觸發(fā)此事件。處理CurrentItemChanged,如果您需要實(shí)現(xiàn)一個(gè)定制的擴(kuò)展通信邏輯,而這個(gè)邏輯不能用導(dǎo)航綁定實(shí)現(xiàn)。
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); }
點(diǎn)擊復(fù)制
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
點(diǎn)擊復(fù)制
導(dǎo)航和編輯按鈕
FileExplorerAssistant擴(kuò)展公開(kāi)了一個(gè)API,允許您管理文件和文件夾。本節(jié)將演示如何使用該API來(lái)實(shí)現(xiàn)類(lèi)似于DevExpress演示中“Two-Panel File Manager”中的操作按鈕。
- DoDefaultAction ——在選定的文件夾中導(dǎo)航,或者在與文件擴(kuò)展名相關(guān)聯(lián)的默認(rèn)程序中打開(kāi)選定的文件(記事本用于.txt文件,照片用于.png文件,等等)。
- Rename ——重命名所選文件或文件夾。
- CopySelectedItem和 MoveSelectedItem ——將選定的文件或文件夾復(fù)制或移動(dòng)到方法參數(shù)指定的位置,在下面的代碼中,所選文件被復(fù)制到另一個(gè)網(wǎng)格的當(dāng)前打開(kāi)的文件夾中。
C#:
gridControlExtension1.CopySelectedItem(gridControlExtension2.CurrentFolder);
點(diǎn)擊復(fù)制
VB.NET:
gridControlExtension1.CopySelectedItem(gridControlExtension2.CurrentFolder)
點(diǎn)擊復(fù)制
- CreateNewFolder ——在當(dāng)前瀏覽的文件夾中創(chuàng)建一個(gè)新目錄。
- GoBack、GoForward、 GoUp——導(dǎo)航方法。
C#:
// Navigate to the parent folder gridControlExtension1.GoUp();
點(diǎn)擊復(fù)制
VB.NET:
' Navigate to the parent folder gridControlExtension1.GoUp()
點(diǎn)擊復(fù)制
- 以“Can”開(kāi)頭的屬性返回是否可以對(duì)當(dāng)前文件夾或文件執(zhí)行相應(yīng)的操作。例如,如果用戶(hù)瀏覽SpecialEnvironmentFolder.Desktop,它們無(wú)法導(dǎo)航到父文件夾(group方法不可用),并且canoup屬性返回false。
C#:
// Set the availability of a button that calls the Rename method btnRename.Enabled = gridControlExtension1.CanRename;
點(diǎn)擊復(fù)制
VB.NET:
' Set the availability of a button that calls the Rename method btnRename.Enabled = gridControlExtension1.CanRename
點(diǎn)擊復(fù)制
- SetCurrentPath and SetCurrentSpecialFolder——允許您瀏覽特定的文件夾或特殊的Windows文件夾。
C#:
breadCrumbExtension1.SetCurrentSpecialFolder(Environment.SpecialFolder.CommonStartMenu); // or breadCrumbExtension1.SetCurrentPath( Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu));
點(diǎn)擊復(fù)制
VB.NET:
breadCrumbExtension1.SetCurrentSpecialFolder(Environment.SpecialFolder.CommonStartMenu) ' or breadCrumbExtension1.SetCurrentPath(Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu))
點(diǎn)擊復(fù)制
自定義層次結(jié)構(gòu)
FileExplorerAssistant組件允許您創(chuàng)建解決方案,不僅可以瀏覽本地存儲(chǔ)上的文件夾,還可以瀏覽虛擬(自定義)層次結(jié)構(gòu)。
要為T(mén)ree List控件創(chuàng)建自定義層次結(jié)構(gòu),請(qǐng)使用VirtualFolderNode和VirtualItemNode實(shí)例填充控件相關(guān)擴(kuò)展的RootNodes集合。
VirtualFolderNode類(lèi)對(duì)象充當(dāng)“folders”,這些對(duì)象具有Nodes集合,您可以使用該集合用子文件夾或項(xiàng)填充它們。
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);
點(diǎn)擊復(fù)制
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)
點(diǎn)擊復(fù)制
VirtualItemNode類(lèi)對(duì)象作為“files”,這些對(duì)象不能嵌入其他文件夾或項(xiàng),也不會(huì)顯示在樹(shù)列表中(類(lèi)似于本地存儲(chǔ)文件)。
C#:
VirtualFolderNode rootNode = new VirtualFolderNode("Root Node"); rootNode.Nodes.Add(new VirtualFolderNode("Child Node 1")); ((VirtualFolderNode)rootNode.Nodes[0]).Nodes.Add(item1);
點(diǎn)擊復(fù)制
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)
點(diǎn)擊復(fù)制
組合虛擬“folder”和“file”對(duì)象,根據(jù)需要?jiǎng)?chuàng)建自定義層次結(jié)構(gòu)。
自定義預(yù)覽
下面的例子演示了如何預(yù)覽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; } }
點(diǎn)擊復(fù)制
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
點(diǎn)擊復(fù)制
自定義上下文菜單
在WinForms文件資源管理器助手組件中處理以下事件來(lái)自定義上下文菜單(添加新命令,隱藏/禁用命令等):
- 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; } }; });
點(diǎn)擊復(fù)制
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)
點(diǎn)擊復(fù)制