windowsforms-17004-controls-and-libraries-editors-and-simple-controls-breadcrumb-edit-control-how-to-create-a-file-explorer.md
This example demonstrates how to use the Breadcrumb Edit control to create a file navigation bar, similar to the one seen in Microsoft Windows Explorer. Two nodes (Root and Computer) are created at design-time as persistent nodes, always visible to an end-user. Their BreadCrumbNode.Persistent and BreadCrumbNode.PopulateOnDemand properties must be set to true. The Root node stores shortcuts to most important directories (Desktop, Windows, Program Files). The Computer node allows end-users to quickly navigate through local disks via related shortcuts. The Nodes tree is dynamically generated at runtime according to the current directories hierarchy. To do so, the RepositoryItemBreadCrumbEdit.ValidatePath, RepositoryItemBreadCrumbEdit.NewNodeAdding and RepositoryItemBreadCrumbEdit.QueryChildNodes events are handled.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DevExpress.Utils.Menu;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Repository;
namespace FileNavigator {
public partial class Form1 : XtraForm {
public static readonly int MaxEntitiesCount = 80;
public Form1() {
InitializeComponent();
Initialize();
}
void myItem_Click(object sender, EventArgs e) {
throw new NotImplementedException();
}
void Properties_QueryPopUp(object sender, CancelEventArgs e) {
throw new NotImplementedException();
}
//Set the Breadcrumb Editor's initial path
void Initialize() {
breadCrumbEdit1.Path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
foreach (DriveInfo driveInfo in GetFixedDrives()) {
breadCrumbEdit1.Properties.History.Add(new BreadCrumbHistoryItem(driveInfo.RootDirectory.ToString()));
}
}
private void breadCrumbEdit1_Properties_NewNodeAdding(object sender, DevExpress.XtraEditors.BreadCrumbNewNodeAddingEventArgs e) {
e.Node.PopulateOnDemand = true;
}
//Check whether or not the target path exists
private void breadCrumbEdit1_Properties_ValidatePath(object sender, DevExpress.XtraEditors.BreadCrumbValidatePathEventArgs e) {
if (!Directory.Exists(e.Path)) {
e.ValidationResult = DevExpress.XtraEditors.BreadCrumbValidatePathResult.Cancel;
return;
}
e.ValidationResult = DevExpress.XtraEditors.BreadCrumbValidatePathResult.CreateNodes;
}
private void breadCrumbEdit1_Properties_QueryChildNodes(object sender, DevExpress.XtraEditors.BreadCrumbQueryChildNodesEventArgs e) {
//Add custom shortcuts to the 'Root' node
if (string.Equals(e.Node.Caption, "Root", StringComparison.Ordinal)) {
InitBreadCrumbRootNode(e.Node);
return;
}
//Add local discs shortcuts to the 'Root' node
if (string.Equals(e.Node.Caption, "Computer", StringComparison.Ordinal)) {
InitBreadCrumbComputerNode(e.Node);
return;
}
//Populate dynamic nodes
string dir = e.Node.Path;
if (!Directory.Exists(dir))
return;
string[] subDirs = GetSubFolders(dir);
for (int i = 0; i < subDirs.Length; i++) {
e.Node.ChildNodes.Add(CreateNode(subDirs[i]));
}
}
void InitBreadCrumbRootNode(BreadCrumbNode node) {
node.ChildNodes.Add(new BreadCrumbNode("Desktop", Environment.GetFolderPath(Environment.SpecialFolder.Desktop)));
node.ChildNodes.Add(new BreadCrumbNode("Windows", Environment.GetFolderPath(Environment.SpecialFolder.Windows)));
node.ChildNodes.Add(new BreadCrumbNode("Program Files", Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)));
}
void InitBreadCrumbComputerNode(BreadCrumbNode node) {
foreach (DriveInfo driveInfo in GetFixedDrives()) {
node.ChildNodes.Add(new BreadCrumbNode(driveInfo.Name, driveInfo.RootDirectory));
}
}
protected BreadCrumbNode CreateNode(string path) {
string folderName = new DirectoryInfo(path).Name;
return new BreadCrumbNode(folderName, folderName, true);
}
//Get the local drives list
public static IEnumerable<DriveInfo> GetFixedDrives() {
foreach (DriveInfo driveInfo in DriveInfo.GetDrives()) {
if (driveInfo.DriveType != DriveType.Fixed) continue;
yield return driveInfo;
}
}
//Get all subfolders contained within the target directory
public static string[] GetSubFolders(string rootDir) {
string[] subDirs = GetSubDirs(rootDir);
if (subDirs == null)
return new string[0];
if (subDirs.Length <= MaxEntitiesCount)
return subDirs;
string[] res = new string[MaxEntitiesCount];
Array.Copy(subDirs, res, res.Length);
return res;
}
//Get the names of the subdirectories
public static string[] GetSubDirs(string dir) {
string[] subDirs = null;
try {
subDirs = Directory.GetDirectories(dir, "*", SearchOption.TopDirectoryOnly);
}
catch { }
return subDirs;
}
private void breadCrumbEdit1_PathChanged(object sender, BreadCrumbPathChangedEventArgs e) {
label2.Text = breadCrumbEdit1.Path;
}
private void breadCrumbEdit1_Properties_PathChanged(object sender, BreadCrumbPathChangedEventArgs e) {
}
}
}
Imports Microsoft.VisualBasic
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.IO
Imports System.Linq
Imports System.Text
Imports System.Threading.Tasks
Imports System.Windows.Forms
Imports DevExpress.Utils.Menu
Imports DevExpress.XtraEditors
Imports DevExpress.XtraEditors.Repository
Namespace FileNavigator
Public Partial Class Form1
Inherits XtraForm
Public Shared ReadOnly MaxEntitiesCount As Integer = 80
Public Sub New()
InitializeComponent()
Initialize()
End Sub
Private Sub myItem_Click(ByVal sender As Object, ByVal e As EventArgs)
Throw New NotImplementedException()
End Sub
Private Sub Properties_QueryPopUp(ByVal sender As Object, ByVal e As CancelEventArgs)
Throw New NotImplementedException()
End Sub
'Set the Breadcrumb Editor's initial path
Private Sub Initialize()
breadCrumbEdit1.Path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
For Each driveInfo As DriveInfo In GetFixedDrives()
breadCrumbEdit1.Properties.History.Add(New BreadCrumbHistoryItem(driveInfo.RootDirectory.ToString()))
Next driveInfo
End Sub
Private Sub breadCrumbEdit1_Properties_NewNodeAdding(ByVal sender As Object, ByVal e As DevExpress.XtraEditors.BreadCrumbNewNodeAddingEventArgs) Handles breadCrumbEdit1.Properties.NewNodeAdding
e.Node.PopulateOnDemand = True
End Sub
'Check whether or not the target path exists
Private Sub breadCrumbEdit1_Properties_ValidatePath(ByVal sender As Object, ByVal e As DevExpress.XtraEditors.BreadCrumbValidatePathEventArgs) Handles breadCrumbEdit1.Properties.ValidatePath
If (Not Directory.Exists(e.Path)) Then
e.ValidationResult = DevExpress.XtraEditors.BreadCrumbValidatePathResult.Cancel
Return
End If
e.ValidationResult = DevExpress.XtraEditors.BreadCrumbValidatePathResult.CreateNodes
End Sub
Private Sub breadCrumbEdit1_Properties_QueryChildNodes(ByVal sender As Object, ByVal e As DevExpress.XtraEditors.BreadCrumbQueryChildNodesEventArgs) Handles breadCrumbEdit1.Properties.QueryChildNodes
'Add custom shortcuts to the 'Root' node
If String.Equals(e.Node.Caption, "Root", StringComparison.Ordinal) Then
InitBreadCrumbRootNode(e.Node)
Return
End If
'Add local discs shortcuts to the 'Root' node
If String.Equals(e.Node.Caption, "Computer", StringComparison.Ordinal) Then
InitBreadCrumbComputerNode(e.Node)
Return
End If
'Populate dynamic nodes
Dim dir As String = e.Node.Path
If (Not Directory.Exists(dir)) Then
Return
End If
Dim subDirs As String() = GetSubFolders(dir)
Dim i As Integer = 0
Do While i < subDirs.Length
e.Node.ChildNodes.Add(CreateNode(subDirs(i)))
i += 1
Loop
End Sub
Private Sub InitBreadCrumbRootNode(ByVal node As BreadCrumbNode)
node.ChildNodes.Add(New BreadCrumbNode("Desktop", Environment.GetFolderPath(Environment.SpecialFolder.Desktop)))
node.ChildNodes.Add(New BreadCrumbNode("Windows", Environment.GetFolderPath(Environment.SpecialFolder.Windows)))
node.ChildNodes.Add(New BreadCrumbNode("Program Files", Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)))
End Sub
Private Sub InitBreadCrumbComputerNode(ByVal node As BreadCrumbNode)
For Each driveInfo As DriveInfo In GetFixedDrives()
node.ChildNodes.Add(New BreadCrumbNode(driveInfo.Name, driveInfo.RootDirectory))
Next driveInfo
End Sub
Protected Function CreateNode(ByVal path As String) As BreadCrumbNode
Dim folderName As String = New DirectoryInfo(path).Name
Return New BreadCrumbNode(folderName, folderName, True)
End Function
'Get the local drives list
Public Shared Iterator Function GetFixedDrives() As IEnumerable(Of DriveInfo)
For Each driveInfo As DriveInfo In DriveInfo.GetDrives()
If driveInfo.DriveType <> DriveType.Fixed Then
Continue For
End If
Yield driveInfo
Next driveInfo
End Function
'Get all subfolders contained within the target directory
Public Shared Function GetSubFolders(ByVal rootDir As String) As String()
Dim subDirs As String() = GetSubDirs(rootDir)
If subDirs Is Nothing Then
Return New String() {}
End If
If subDirs.Length <= MaxEntitiesCount Then
Return subDirs
End If
Dim res As String() = New String(MaxEntitiesCount - 1) {}
Array.Copy(subDirs, res, res.Length)
Return res
End Function
'Get the names of the subdirectories
Public Shared Function GetSubDirs(ByVal dir As String) As String()
Dim subDirs As String() = Nothing
Try
subDirs = Directory.GetDirectories(dir, "*", SearchOption.TopDirectoryOnly)
Catch
End Try
Return subDirs
End Function
Private Sub breadCrumbEdit1_PathChanged(ByVal sender As Object, ByVal e As BreadCrumbPathChangedEventArgs) Handles breadCrumbEdit1.PathChanged
label2.Text = breadCrumbEdit1.Path
End Sub
Private Sub breadCrumbEdit1_Properties_PathChanged(ByVal sender As Object, ByVal e As BreadCrumbPathChangedEventArgs) Handles breadCrumbEdit1.Properties.PathChanged
End Sub
End Class
End Namespace