File Explorer is a simple, fast, and user‑friendly file management application designed to make navigating, organizing, and manipulating files intuitive for all users. It combines a clean graphical interface with a powerful built‑in Command Line Interface (CLI) for users who prefer keyboard‑driven workflows.
- Navigation: Browse directories using a tree view and list view.
- File Operations: Perform essential actions such as:
- Change Directory (
cd) - Copy files and directories (
copy) - Move files and directories (
move) - Delete files and directories (
delete)
- Change Directory (
- Clipboard Support: Cut, copy, and paste files and folders.
- Context Menu: Right‑click menus for quick access to common actions.
- History Tracking: Move backward and forward through previously visited directories.
- File Type Icons: Visual indicators for different file types.
- Status Bar: Real‑time feedback on operations and system status.
For users who enjoy the speed and precision of typed commands, the built‑in CLI provides:
- Fast directory navigation (
cd) - File and folder operations (
copy,move,delete,rename) - Text file creation (
text,txt) - Search and result cycling (
find,findnext) - Contextual path handling (type a path to open it)
- Quoting rules for paths with spaces
- Helpful usage messages and error feedback
- A built‑in
helpcommand with full documentation
The CLI and GUI work together seamlessly, giving users the freedom to choose the workflow that suits them best.
I set out to build my own File Explorer because I wanted to understand, from the ground up, how a core part of every operating system actually works. We all use file managers every day, but it’s easy to overlook how much is happening behind the scenes: navigation history, sorting, file type detection, context menus, clipboard operations, lazy loading of folder trees, and many other details. Recreating these features myself has been a practical way to explore system I/O, UI design, event handling, and performance considerations in a hands-on, exploratory way.
This project is not meant to replace the built-in Windows Explorer. Instead, it serves as a learning environment, a place where I can experiment, break things, fix them, and understand why they work the way they do. By rebuilding something familiar, I get to uncover the subtle engineering decisions that make everyday tools feel intuitive, similar to how art students copy the masters to study technique and intention.
This project is designed for anyone who wants to understand how real applications work, from beginners taking their first steps, to experienced developers exploring deeper architectural ideas. My hope is that you come away with:
By looking at the code behind navigation, file operations, and directory structures, you can see how your operating system performs these tasks under the hood.
The project demonstrates UI layout, event‑driven programming, keyboard shortcuts, tooltips, context menus, and the small design decisions that make an interface feel intuitive and predictable.
You’ll find subsystems for navigation history, sorting logic, search functionality, and file-type mapping-all working together in a cohesive, maintainable way.
Everything is open-source under the MIT License, so you’re free to explore, customize, or reuse any part of the codebase in your own applications.
Re-creating something familiar is one of the most effective ways to deepen your understanding. Much like how art students copy the masters to study technique, rebuilding a tool like File Explorer reveals the subtle decisions and hidden complexity behind everyday software.
If you’re curious, the GitHub repository includes the full source code and documentation. I’d love to hear your thoughts, suggestions, or ideas for future features. This project is as much about learning as it is about building something functional, and I’m excited to share that journey with you.
-
Code Walkthrough
-
🖥️ Command Line Interface (CLI)
- Features Overview
- Commands
- cd — Change Directory
- mkdir / make — Create Directory
- copy — Copy Files or Folders
- move — Move Files or Folders
- delete — Delete Files or Folders
- rename — Rename Files or Folders
- text / txt — Create Text Files
- open — Open Files or Folders
- find / search — Search
- findnext / searchnext — Next Search Result
- help — Show Help
- Quoting Rules
- Contextual Navigation
- Example Session
The Command Line Interface (CLI) is an integrated text‑based command system inside the File Explorer application. It allows users to navigate folders, manage files, and perform common operations quickly using typed commands.
The CLI is designed to be:
- Fast - no menus, no dialogs
- Predictable - clear rules and consistent behavior
- Beginner‑friendly - helpful messages and examples
- Powerful - supports navigation, search, file operations, and more
- Change directories
- Open files directly
- Navigate to folders by typing their path
- Supports paths with spaces using quotes
- Create, copy, move, rename, and delete
- Works with both files and directories
- Handles quoted paths safely
- Search the current folder
- Cycle through results with
findnext - Highlights and selects results in the UI
If a command doesn’t match a known keyword, the CLI checks:
- Is it a folder? → Navigate to it
- Is it a file? → Open it
- Otherwise → “Unknown command”
This makes the CLI feel natural and forgiving.
Below is the complete list of supported commands, including syntax, descriptions, and examples.
Usage:
cd [directory]
Description:
Changes the current working directory.
Examples:
cd C:\
cd "C:\My Folder"
Usage:
mkdir [directory_path]
Description:
Creates a new folder.
Examples:
mkdir C:\newfolder
make "C:\My New Folder"
Usage:
copy [source] [destination]
Description:
Copies a file or folder to a destination directory.
Examples:
copy C:\folderA\file.txt C:\folderB
copy "C:\folder A" "C:\folder B"
Usage:
move [source] [destination]
Description:
Moves a file or folder to a new location.
Examples:
move C:\folderA\file.txt C:\folderB\file.txt
move "C:\folder A\file.txt" "C:\folder B\renamed.txt"
Usage:
delete [file_or_directory]
Description:
Deletes a file or folder.
Examples:
delete C:\file.txt
delete "C:\My Folder"
Usage:
rename [source_path] [new_name]
Important:
Paths containing spaces must be enclosed in quotes.
Examples:
rename "C:\folder\oldname.txt" "newname.txt"
rename "C:\folder\old name.txt" "new name.txt"
Usage:
text [file_path]
Description:
Creates a new text file at the specified path and opens it.
Example:
text "C:\folder\example.txt"
If no file name is provided, the CLI creates a new file named:
New Text File.txt
Usage:
open [file_or_directory]
Description:
Opens a file with its default application, or navigates into a folder.
If no path is provided, the command opens the currently selected file or folder in the File Explorer list.
Examples:
open C:\folder\file.txt
open "C:\My Folder"
open
Behavior:
- If the target is a file → opens it using the default program
- If the target is a folder → navigates into it
- If nothing is selected and no path is provided → shows usage help
- Supports quoted paths with spaces
Usage:
find [search_term]
Description:
Searches the current folder for files or folders containing the term.
Example:
find report
If results are found:
- The first result is automatically selected
- The status bar shows how many matches were found
Usage:
findnext
Description:
Cycles to the next result from the previous search.
Wraps around when reaching the end.
Closes the application.
Displays the full list of commands.
Paths containing spaces must be enclosed in quotes:
"C:\My Folder"
"C:\Users\Joe\My File.txt"
This applies to:
cdcopymoverenamedeletetext
The CLI will warn the user when quotes are required.
If the user enters something that is not a command:
- If it’s a folder path, the CLI navigates to it
- If it’s a file path, the CLI opens it
- Otherwise, the CLI shows an “Unknown command” message
This makes the CLI feel natural and forgiving.
> cd C:\Users\Joe
Navigated To: C:\Users\Joe
> copy "C:\Users\Joe\file.txt" "C:\Users\Joe\Documents"
Copied file: file.txt to: C:\Users\Joe\Documents
> find report
Found 3 result(s). Showing result 1. Type findnext to move to the next match.
> findnext
Showing result 2 of 3
> help
(Displays full help text)
The File Explorer CLI provides:
- Fast directory navigation
- Powerful file operations
- Search with result cycling
- Intelligent path handling
- Clear feedback and usage messages
- Beginner‑friendly quoting rules
- Contextual file/folder opening
It’s a flexible, efficient alternative to the graphical interface - perfect for users who enjoy command‑driven workflows.
This method renames either a file or a folder, following a clear set of safety rules. Each rule protects the user from mistakes and helps them understand what’s happening.
Below is the full code, then we’ll walk through it one step at a time.
Private Sub RenameFileOrDirectory(sourcePath As String, newName As String)
Dim newPath As String = Path.Combine(Path.GetDirectoryName(sourcePath), newName)
' Rule 1: Path must be absolute (start with C:\ or similar).
' Reject relative paths outright
If Not Path.IsPathRooted(sourcePath) Then
ShowStatus(IconDialog & " Rename failed: Path must be absolute. Example: C:\folder")
Exit Sub
End If
' Rule 2: Protected paths are never renamed.
' Check if the path is in the protected list
If IsProtectedPathOrFolder(sourcePath) Then
' The path is protected; prevent rename
' Show user the directory so they can see it wasn't renamed.
NavigateTo(sourcePath)
' Notify the user of the prevention so the user knows why it didn't rename.
ShowStatus(IconProtect & " Rename prevented for protected path or folder: " & sourcePath)
Exit Sub
End If
Try
' Rule 3: If it’s a folder, rename the folder and show the new folder.
' If source is a directory
If Directory.Exists(sourcePath) Then
' Rename directory
Directory.Move(sourcePath, newPath)
' Navigate to the renamed directory
NavigateTo(newPath)
ShowStatus(IconSuccess & " Renamed Folder to: " & newName)
' Rule 4: If it’s a file, rename the file and show its folder.
' If source is a file
ElseIf File.Exists(sourcePath) Then
' Rename file
File.Move(sourcePath, newPath)
' Navigate to the directory of the renamed file
NavigateTo(Path.GetDirectoryName(sourcePath))
ShowStatus(IconSuccess & " Renamed File to: " & newName)
' Rule 5: If nothing exists at that path, explain the quoting rule for spaces.
Else
' Path does not exist
ShowStatus(IconError & " Renamed failed: No path. Paths with spaces must be enclosed in quotes. Example: rename ""[source_path]"" ""[new_name]"" e.g., rename ""C:\folder\old name.txt"" ""new name.txt""")
End If
Catch ex As Exception
' Rule 6: If anything goes wrong,show a status message.
ShowStatus(IconError & " Rename failed: " & ex.Message)
Debug.WriteLine("RenameFileOrDirectory Error: " & ex.Message)
End Try
End Sub
Private Sub RenameFileOrDirectory(sourcePath As String, newName As String)- sourcePath — the full path to the file or folder you want to rename
- newName — just the new name (not a full path)
Dim newPath As String = Path.Combine(Path.GetDirectoryName(sourcePath), newName)- Extracts the folder that contains the item
- Combines it with the new name
- Example:
sourcePath = "C:\Stuff\Old.txt"newName = "New.txt"newPath = "C:\Stuff\New.txt"
If Not Path.IsPathRooted(sourcePath) Then
ShowStatus(IconDialog & " Rename failed: Path must be absolute. Example: C:\folder")
Exit Sub
End IfBeginners often type relative paths like folder\file.txt.
This rule stops the rename and explains the correct format.
If IsProtectedPathOrFolder(sourcePath) Then
NavigateTo(sourcePath)
ShowStatus(IconProtect & " Rename prevented for protected path or folder: " & sourcePath)
Exit Sub
End IfSome paths should never be renamed (system folders, app folders, etc.).
This rule:
- Prevents the rename
- Shows the user the original folder
- Explains why the rename was blocked
This is excellent for learner clarity.
Try
...
Catch ex As Exception
ShowStatus(IconError & " Rename failed: " & ex.Message)
Debug.WriteLine("RenameFileOrDirectory Error: " & ex.Message)
End TryAnything inside the Try block that fails will be caught and explained.
Beginners get a friendly message instead of a crash.
If Directory.Exists(sourcePath) Then
Directory.Move(sourcePath, newPath)
NavigateTo(newPath)
ShowStatus(IconSuccess & " Renamed Folder to: " & newName)- Checks if the path points to a directory
- Renames it
- Shows the user the newly renamed folder
This reinforces the idea that folders are “containers” and have their own identity.
ElseIf File.Exists(sourcePath) Then
File.Move(sourcePath, newPath)
NavigateTo(Path.GetDirectoryName(sourcePath))
ShowStatus(IconSuccess & " Renamed File to: " & newName)- Checks if the path points to a file
- Renames it
- Shows the user the folder containing the renamed file
This keeps the UI consistent and predictable.
Else
ShowStatus(IconError & " Renamed failed: No path. Paths with spaces must be enclosed in quotes. Example: rename ""[source_path]"" ""[new_name]"" e.g., rename ""C:\folder\old name.txt"" ""new name.txt""")
End IfBeginners often forget to quote paths with spaces.
This rule:
- Detects the missing path
- Explains the quoting rule
- Gives both a template and a real example
This is excellent pedagogy.
Catch ex As Exception
ShowStatus(IconError & " Rename failed: " & ex.Message)
Debug.WriteLine("RenameFileOrDirectory Error: " & ex.Message)
End Try- No crashes
- Clear feedback
- Debug info for you
This method teaches six important rules:
- Paths must be absolute
- Protected paths cannot be renamed
- Folders are renamed and then shown
- Files are renamed and their folder is shown
- Missing paths trigger a helpful quoting explanation
- Any error is caught and explained safely
This method copies an entire directory — including all files and all subfolders — into a new destination. It uses recursion, meaning the method calls itself to handle deeper levels of folders.
Below is the full code, then we’ll walk through it one step at a time.
Private Async Function CopyDirectory(sourceDir As String, destDir As String) As Task
Dim dirInfo As New DirectoryInfo(sourceDir)
If Not dirInfo.Exists Then
ShowStatus(IconError & " Source directory not found: " & sourceDir)
Return
End If
Try
ShowStatus(IconCopy & " Creating destination directory: " & destDir)
' Create destination directory
Try
Directory.CreateDirectory(destDir)
Catch ex As Exception
ShowStatus(IconError & " Failed to create destination directory: " & ex.Message)
Return
End Try
ShowStatus(IconCopy & " Copying files to destination directory: " & destDir)
' Copy files asynchronously
For Each file In dirInfo.GetFiles()
Try
Dim targetFilePath = Path.Combine(destDir, file.Name)
Await Task.Run(Sub() file.CopyTo(targetFilePath, overwrite:=True))
Debug.WriteLine("Copied file: " & targetFilePath) ' Log successful copy
Catch ex As UnauthorizedAccessException
Debug.WriteLine("CopyDirectory Error (Unauthorized): " & ex.Message)
ShowStatus(IconError & " Unauthorized access: " & file.FullName)
Catch ex As Exception
Debug.WriteLine("CopyDirectory Error: " & ex.Message)
ShowStatus(IconError & " Copy failed for file: " & file.FullName & " - " & ex.Message)
End Try
Next
ShowStatus(IconCopy & " Copying subdirectories.")
' Copy subdirectories recursively asynchronously
For Each subDir In dirInfo.GetDirectories()
Dim newDest = Path.Combine(destDir, subDir.Name)
Try
Await CopyDirectory(subDir.FullName, newDest)
Catch ex As Exception
Debug.WriteLine("CopyDirectory Error: " & ex.Message)
End Try
Next
' Refresh the view to show the copied directory
NavigateTo(destDir)
ShowStatus(IconSuccess & " Copied into " & destDir)
Catch ex As Exception
ShowStatus(IconError & " Copy failed: " & ex.Message)
Debug.WriteLine("CopyDirectory Error: " & ex.Message)
End Try
End Function
Here's a detailed breakdown of the updated CopyDirectory method , which now supports asynchronous file copying. This ensures that the UI remains responsive during the operation, especially when dealing with large directories.
Private Async Function CopyDirectory(sourceDir As String, destDir As String) As Task- sourceDir: The folder you want to copy.
- destDir: The location where the copy should be created.
Dim dirInfo As New DirectoryInfo(sourceDir)- This creates a
DirectoryInfoobject that provides access to the folder's files and subfolders.
If Not dirInfo.Exists Then
ShowStatus(IconError & " Source directory not found: " & sourceDir)
Return
End If- Checks if the source directory exists. If not, it shows an error message and exits the method.
Try- Initiates a block to handle exceptions that may occur during the operation.
Try
Directory.CreateDirectory(destDir)
Catch ex As Exception
ShowStatus(IconError & " Failed to create destination directory: " & ex.Message)
Return
End Try- Attempts to create the destination directory. If it fails, an error message is shown, and the method exits.
For Each file In dirInfo.GetFiles()
Try
Dim targetFilePath = Path.Combine(destDir, file.Name)
Await Task.Run(Sub() file.CopyTo(targetFilePath, overwrite:=True))
Debug.WriteLine("Copied file: " & targetFilePath) ' Log successful copy
Catch ex As UnauthorizedAccessException
Debug.WriteLine("CopyDirectory Error (Unauthorized): " & ex.Message)
ShowStatus(IconError & " Unauthorized access: " & file.FullName)
Catch ex As Exception
Debug.WriteLine("CopyDirectory Error: " & ex.Message)
ShowStatus(IconError & " Copy failed for file: " & file.FullName & " - " & ex.Message)
End Try
Next- Iterates through each file in the source directory and copies it to the destination asynchronously.
- Uses
Await Task.Run(...)to ensure the UI remains responsive during the file copy process. - Handles exceptions specifically for unauthorized access and general errors.
For Each subDir In dirInfo.GetDirectories()
Dim newDest = Path.Combine(destDir, subDir.Name)
Try
Await CopyDirectory(subDir.FullName, newDest)
Catch ex As Exception
Debug.WriteLine("CopyDirectory Error: " & ex.Message)
End Try
Next- For each subdirectory, constructs a new destination path and calls
CopyDirectoryrecursively. - Utilizes
Awaitfor asynchronous execution.
NavigateTo(destDir)- Updates the UI to reflect the new state after the copy operation is complete.
ShowStatus(IconSuccess & " Copied into " & destDir)- Displays a success message once the operation is completed.
Catch ex As Exception
ShowStatus(IconError & " Copy failed: " & ex.Message)
Debug.WriteLine("CopyDirectory Error: " & ex.Message)
End Try- If any errors occur during the overall operation, they are caught here, and an appropriate message is displayed.
- Asynchronous Support: The method now uses
AsyncandAwaitto ensure the application remains responsive during file operations. - Enhanced Error Handling: Specific handling for unauthorized access and general exceptions.
- User Feedback: Continuous feedback is provided to the user throughout the process.
This updated method demonstrates how to effectively manage file copying operations while maintaining a responsive user interface.
This diagram shows exactly how the CopyDirectory routine walks the tree.
Imagine your folder structure looks like this:
SourceDir
├── FileA.txt
├── FileB.txt
├── Sub1
│ ├── FileC.txt
│ └── Sub1A
│ └── FileD.txt
└── Sub2
└── FileE.txt
The method processes it in this exact order.
CopyDirectory(SourceDir, DestDir)
│
├── Copy files in SourceDir
│
├── For each subdirectory:
│ ├── CopyDirectory(Sub1, DestDir/Sub1)
│ │ ├── Copy files in Sub1
│ │ ├── CopyDirectory(Sub1A, DestDir/Sub1/Sub1A)
│ │ │ ├── Copy files in Sub1A
│ │ │ └── (Sub1A has no more subfolders → return)
│ │ └── (Sub1 done → return)
│ │
│ └── CopyDirectory(Sub2, DestDir/Sub2)
│ ├── Copy files in Sub2
│ └── (Sub2 has no more subfolders → return)
│
└── All subdirectories processed → return to caller
This shows how the call stack grows and shrinks as recursion happens.
Call 1: CopyDirectory(SourceDir)
├── copies files
├── enters Sub1 → Call 2
Call 2: CopyDirectory(Sub1)
├── copies files
├── enters Sub1A → Call 3
Call 3: CopyDirectory(Sub1A)
├── copies files
└── no subfolders → return to Call 2
Back to Call 2:
└── Sub1 done → return to Call 1
Back to Call 1:
├── enters Sub2 → Call 4
Call 4: CopyDirectory(Sub2)
├── copies files
└── no subfolders → return to Call 1
Back to Call 1:
└── all done → return to caller
Each level of indentation = one level deeper in recursion.
CopyDirectory(SourceDir)
CopyDirectory(Sub1)
CopyDirectory(Sub1A)
CopyDirectory(Sub2)
This is the simplest way to show the “shape” of recursion.
- Start at the root folder.
- Copy its files.
- For each subfolder:
- Step into it
- Treat it like a brand‑new root
- Copy its files
- Repeat the process for its subfolders
- When a folder has no subfolders, return to the previous level.
- Continue until you climb all the way back to the top.
This walkthrough explains how the MoveFileOrDirectory routine works inside the file‑manager project. The goal of this method is to safely move files or directories while providing clear, user‑friendly feedback and preventing dangerous or confusing operations.
MoveFileOrDirectory(source, destination) performs a safe move operation with:
- Input validation
- Protected‑path checks
- Self‑move and recursive‑move prevention
- Automatic creation of destination directories
- User‑visible navigation before and after the move
- Clear status messages for every outcome
This mirrors the project’s design philosophy:
Show → Confirm → Act → Show Result
Private Sub MoveFileOrDirectory(source As String, destination As String)
Try
' Validate parameters
If String.IsNullOrWhiteSpace(source) OrElse String.IsNullOrWhiteSpace(destination) Then
ShowStatus(IconWarning & " Source or destination path is invalid.")
Return
End If
' If source and destination are the same, do nothing
If String.Equals(source.TrimEnd("\"c), destination.TrimEnd("\"c), StringComparison.OrdinalIgnoreCase) Then
ShowStatus(IconWarning & " Source and destination paths are the same. Move operation canceled.")
Return
End If
' Is source on the protected paths list?
If IsProtectedPathOrFolder(source) Then
ShowStatus(IconProtect & " Move operation prevented for protected path: " & source)
Return
End If
' Is destination on the protected paths list?
If IsProtectedPathOrFolder(destination) Then
ShowStatus(IconProtect & " Move operation prevented for protected path: " & destination)
Return
End If
' Prevent moving a directory into itself or its subdirectory
If Directory.Exists(source) AndAlso
(String.Equals(source.TrimEnd("\"c), destination.TrimEnd("\"c), StringComparison.OrdinalIgnoreCase) OrElse
destination.StartsWith(source.TrimEnd("\"c) & "\", StringComparison.OrdinalIgnoreCase)) Then
ShowStatus(IconWarning & " Cannot move a directory into itself or its subdirectory.")
Return
End If
' Check if the source is a file
If File.Exists(source) Then
' Check if the destination file already exists
If Not File.Exists(destination) Then
' Navigate to the directory of the source file
NavigateTo(Path.GetDirectoryName(source))
ShowStatus(IconDialog & " Moving file to: " & destination)
' Ensure destination directory exists
Directory.CreateDirectory(Path.GetDirectoryName(destination))
File.Move(source, destination)
' Navigate to the destination folder
NavigateTo(Path.GetDirectoryName(destination))
ShowStatus(IconSuccess & " Moved file to: " & destination)
Else
ShowStatus(IconWarning & " Destination file already exists.")
End If
ElseIf Directory.Exists(source) Then
' Check if the destination directory already exists
If Not Directory.Exists(destination) Then
' Navigate to the directory being moved so the user can see it
NavigateTo(source)
ShowStatus(IconDialog & " Moving directory to: " & destination)
' Ensure destination parent exists
Directory.CreateDirectory(Path.GetDirectoryName(destination))
' Perform the move
Directory.Move(source, destination)
' Navigate to the new location FIRST
NavigateTo(destination)
' Now refresh the tree roots
InitTreeRoots()
ShowStatus(IconSuccess & " Moved directory to: " & destination)
Else
ShowStatus(IconWarning & " Destination directory already exists.")
End If
Else
ShowStatus(IconWarning & " Move failed: Source path not found. Paths with spaces must be enclosed in quotes. Example: move ""C:\folder A"" ""C:\folder B""")
End If
Catch ex As Exception
ShowStatus(IconError & " Move failed: " & ex.Message)
Debug.WriteLine("MoveFileOrDirectory Error: " & ex.Message)
End Try
End SubRejects empty or whitespace paths to prevent confusing errors.
If the source and destination resolve to the same location, the move is canceled.
Both source and destination are checked against a protected‑paths list.
Protected paths cannot be moved.
The method prevents moving a directory into:
- Itself
- One of its own subdirectories
This avoids catastrophic recursive behavior.
If the source is a file:
- Navigate to the file’s directory
- Ensure the destination directory exists
- Move the file
- Navigate to the destination folder
- Show success
If the source is a directory:
- Navigate into the directory being moved
- Ensure the destination parent exists
- Move the directory
- Navigate to the new location
- Refresh the tree
- Show success
Any exception results in:
- A user‑friendly status message
- A debug log entry
This method is built around clarity, safety, and emotional transparency:
- The user always sees what is about to happen
- The user always sees the result
- Dangerous operations are prevented
- All actions are narrated through status messages
- The UI updates in a way that reinforces the mental model
This makes the file manager not just functional — but guiding.
The NavigateTo method is responsible for navigating to a specified folder path.
Below is the full code, then we’ll walk through it one step at a time.
Private Sub NavigateTo(path As String, Optional recordHistory As Boolean = True)
' Navigate to the specified folder path.
' Updates the current folder, path textbox, and file list.
If String.IsNullOrWhiteSpace(path) Then Exit Sub
' Validate that the folder exists
If Not Directory.Exists(path) Then
MessageBox.Show("Folder not found: " & path, "Navigation", MessageBoxButtons.OK, MessageBoxIcon.Information)
ShowStatus(IconWarning & " Folder not found: " & path)
Exit Sub
End If
' If this method is called from a background thread, invoke it on the UI thread
If txtPath.InvokeRequired Then
txtPath.Invoke(New Action(Of String)(AddressOf NavigateTo), path, recordHistory)
Return
End If
ShowStatus(IconNavigate & " Navigated To: " & path)
currentFolder = path
txtPath.Text = path
PopulateFiles(path)
If recordHistory Then
' Trim forward history if we branch
If _historyIndex >= 0 AndAlso _historyIndex < _history.Count - 1 Then
_history.RemoveRange(_historyIndex + 1, _history.Count - (_historyIndex + 1))
End If
_history.Add(path)
_historyIndex = _history.Count - 1
UpdateNavButtons()
End If
UpdateFileButtons()
UpdateEditButtons()
UpdateEditContextMenu()
End Sub
Here's a detailed breakdown of the NavigateTo method in VB.NET, which is responsible for navigating to a specified folder path. This method updates the UI components accordingly and manages navigation history.
Private Sub NavigateTo(path As String, Optional recordHistory As Boolean = True)- path: The folder path to navigate to.
- recordHistory: An optional boolean parameter that indicates whether the navigation should be recorded in history (default is
True).
If String.IsNullOrWhiteSpace(path) Then Exit Sub- Checks if the provided path is null, empty, or consists only of whitespace. If so, the method exits early.
If Not Directory.Exists(path) Then
MessageBox.Show("Folder not found: " & path, "Navigation", MessageBoxButtons.OK, MessageBoxIcon.Information)
ShowStatus(IconWarning & " Folder not found: " & path)
Exit Sub
End If- Validates that the specified folder exists. If it does not, a message box is displayed to inform the user, and a warning status is shown. The method then exits.
If txtPath.InvokeRequired Then
txtPath.Invoke(New Action(Of String)(AddressOf NavigateTo), path, recordHistory)
Return
End If- Checks if the method is being called from a background thread (indicated by
InvokeRequired). If so, it invokes the method on the UI thread usingInvoke, ensuring that UI updates are performed on the correct thread.
ShowStatus(IconNavigate & " Navigated To: " & path)
currentFolder = path
txtPath.Text = path
PopulateFiles(path)- Updates the status to indicate the navigation action.
- Sets the
currentFoldervariable to the new path. - Updates the text box (
txtPath) with the new path. - Calls
PopulateFiles(path)to refresh the file list displayed in the UI.
If recordHistory Then
' Trim forward history if we branch
If _historyIndex >= 0 AndAlso _historyIndex < _history.Count - 1 Then
_history.RemoveRange(_historyIndex + 1, _history.Count - (_historyIndex + 1))
End If
_history.Add(path)
_historyIndex = _history.Count - 1
UpdateNavButtons()
End If- If
recordHistoryisTrue, it manages the navigation history:- Trims the forward history if the current index is not at the end of the history list.
- Adds the new path to the history list.
- Updates the
_historyIndexto point to the last entry in the history. - Calls
UpdateNavButtons()to refresh the navigation buttons (e.g., back and forward).
UpdateFileButtons()
UpdateEditButtons()
UpdateEditContextMenu()- Calls methods to update various UI elements related to file actions, editing, and context menus, ensuring they reflect the current state after navigation.
The NavigateTo method effectively handles folder navigation with the following key features:
- Input Validation: Checks for valid paths and existence of directories.
- Thread Safety: Ensures UI updates occur on the correct thread.
- User Feedback: Provides immediate feedback on navigation actions and errors.
- History Management: Maintains a history of navigated folders, allowing for backward and forward navigation.
- UI Updates: Refreshes relevant UI components to reflect the current folder state.
This method is essential for any file management application, ensuring smooth and intuitive navigation for users.
This code takes the user’s search term, finds matching files in the current folder, highlights the first match, shows how many results there are, and gives the user a clean, Explorer‑style search experience.
Think of this code as the “start a search” feature in our file explorer.
When the user types something like:
find report
this block of code runs.
Case "find", "search"
If parts.Length > 1 Then
Dim searchTerm As String = String.Join(" ", parts.Skip(1)).Trim()
If String.IsNullOrWhiteSpace(searchTerm) Then
ShowStatus(
StatusPad & IconDialog &
" Usage: find [search_term] Example: find document"
)
Return
End If
' Announce search
ShowStatus(StatusPad & IconSearch & " Searching for: " & searchTerm)
' Perform search
OnlySearchForFilesInCurrentFolder(searchTerm)
' Reset index for new search
SearchIndex = 0
RestoreBackground()
' If results exist, auto-select the first one
If SearchResults.Count > 0 Then
lvFiles.SelectedItems.Clear()
SelectListViewItemByPath(SearchResults(0))
Dim nextPath As String = SearchResults(SearchIndex)
Dim fileName As String = Path.GetFileNameWithoutExtension(nextPath)
lvFiles.Focus()
HighlightSearchMatches()
' Unified search HUD
ShowStatus(
StatusPad & IconSearch &
$" Result {SearchIndex + 1} of {SearchResults.Count} ""{fileName}"" Next F3 Open Ctrl+O Reset Esc"
)
Else
ShowStatus(
StatusPad & IconDialog &
" No results found for: " & searchTerm
)
End If
Else
ShowStatus(
StatusPad & IconDialog &
" Usage: find [search_term] Example: find document"
)
End If
Return
Let’s go through it step by step.
Make sure the user actually typed a search term
If parts.Length > 1 Thenpartsis the command split into words.- If the user typed only
findwith nothing after it, then there’s nothing to search for.
Combine everything after the command into one search term
Dim searchTerm As String = String.Join(" ", parts.Skip(1)).Trim()- This takes everything after the word
findand turns it into one string. - Example:
find my report→"my report"
If the search term is empty, show a helpful message
If String.IsNullOrWhiteSpace(searchTerm) Then
ShowStatus("Usage: find [search_term] Example: find document")
Return
End If- This protects the user from mistakes.
- It stops the command early and explains how to use it.
Tell the user that the search has started
ShowStatus("Searching for: " & searchTerm)- This updates your status bar so the user knows something is happening.
Actually perform the search
OnlySearchForFilesInCurrentFolder(searchTerm)- This is your search engine.
- It looks through the current folder and fills
SearchResultswith matching file paths.
Reset the search index
SearchIndex = 0
RestoreBackground()- Since this is a new search, you always start at the first result.
RestoreBackground()clears any old highlighting from a previous search.
If matches were found…
If SearchResults.Count > 0 ThenNow the fun part begins.
Select the first matching file
lvFiles.SelectedItems.Clear()
SelectListViewItemByPath(SearchResults(0))- Clears any previous selection.
- Highlights the first matching file in the ListView.
- Scrolls to it so the user can see it.
Get a clean file name for display
Dim nextPath As String = SearchResults(SearchIndex)
Dim fileName As String = Path.GetFileNameWithoutExtension(nextPath)- Turns something like
C:\Users\Joseph\Documents\Report1.pdf
into
"Report1"
Focus the ListView and highlight all matches
lvFiles.Focus()
HighlightSearchMatches()- Gives keyboard focus to the file list.
- Highlights all matching items.
Show the unified search HUD
ShowStatus(
$"Result {SearchIndex + 1} of {SearchResults.Count} ""{fileName}"" Next F3 Open Ctrl+O Reset Esc"
)This status message that tells the user:
- Which result they’re on
- How many results exist
- The file name
- Helpful keyboard shortcuts
If no results were found…
Else
ShowStatus("No results found for: " & searchTerm)
End If- The app gently tells the user nothing matched.
If the user typed only “find” with no term
Else
ShowStatus("Usage: find [search_term] Example: find document")
End If- Another friendly reminder about how to use the command.
This method cycles to the next search result, highlights it in the file list, scrolls to it, and updates the status bar so the user always knows where they are and what they can do next.
Below is the full code, then we’ll walk through it one step at a time.
Private Sub HandleFindNextCommand()
' No active search
If SearchResults.Count = 0 Then
ShowStatus(
StatusPad & IconDialog &
" No previous search results. Press Ctrl+F or enter: find [search_term] to start a search."
)
Return
End If
' Advance index with wraparound
SearchIndex += 1
If SearchIndex >= SearchResults.Count Then
SearchIndex = 0
End If
' Select the next result
lvFiles.SelectedItems.Clear()
Dim nextPath As String = SearchResults(SearchIndex)
SelectListViewItemByPath(nextPath)
Dim fileName As String = Path.GetFileNameWithoutExtension(nextPath)
' Status HUD
ShowStatus(
StatusPad & IconSearch &
$" Result {SearchIndex + 1} of {SearchResults.Count} ""{fileName}"" Next F3 Open Ctrl+O Reset Esc"
)
End Sub
Private Sub HandleFindNextCommand()- This defines a subroutine (a block of code) named
HandleFindNextCommand. - It runs whenever the user triggers the “Find Next” action — for example, pressing F3 or typing
findnext.
' No active search
If SearchResults.Count = 0 Then- This checks whether there are any search results stored.
SearchResultsis a list of file paths found by the last search.- If the list is empty (
Count = 0), it means the user hasn’t searched yet.
ShowStatus(
StatusPad & IconDialog &
" No previous search results. Press Ctrl+F or enter: find [search_term] to start a search."
)- This displays a friendly message in your status bar.
StatusPadandIconDialogare just decorative pieces that make the message look nice.- The message tells the user how to start a search.
Return
End IfReturnstops the subroutine immediately.- Since there are no results, there’s nothing else to do.
' Advance index with wraparound
SearchIndex += 1- This moves to the next search result.
SearchIndexkeeps track of which result is currently selected.+= 1means “add 1 to the current value.”
If SearchIndex >= SearchResults.Count Then
SearchIndex = 0
End If- This handles wraparound.
- If the index goes past the last result, it jumps back to the first one.
- This creates a loop: last → first → second → etc.
- It feels like how Explorer cycles through search results.
' Select the next result
lvFiles.SelectedItems.Clear()- Clears any previous selection in the file list.
- This ensures only the new result is highlighted.
Dim nextPath As String = SearchResults(SearchIndex)- Retrieves the file path of the next search result.
- Stores it in a variable named
nextPath.
SelectListViewItemByPath(nextPath)- This is our helper function that:
- Finds the matching item in the ListView.
- Selects the item.
- Scrolls the ListView so the item is visible.
- This is what makes the UI jump to the matching file.
Dim fileName As String = Path.GetFileNameWithoutExtension(nextPath)- Extracts just the file name (no folder, no extension).
- This is used for a cleaner status message.
' Status HUD
ShowStatus(
StatusPad & IconSearch &
$" Result {SearchIndex + 1} of {SearchResults.Count} ""{fileName}"" Next F3 Open Ctrl+O Reset Esc"
)- Updates the status bar with a compact “search HUD.”
- It shows:
- Which result you’re on
(Result 3 of 12) - The file name
("Report Q1") - Helpful keyboard shortcuts
(Next F3,Open Ctrl+O,Reset Esc)
- Which result you’re on
SearchIndex + 1is used because lists start at 0, but humans start at 1.
End Sub- Marks the end of the subroutine.
This helper is a quiet hero in our search system. It ensures that:
- The correct file is highlighted
- The UI scrolls to it
- Keyboard navigation starts from the right place
- The user feels like the app “knows where they are”
Below is the full code, then we’ll walk through it one step at a time.
Private Sub SelectListViewItemByPath(fullPath As String)
For Each item As ListViewItem In lvFiles.Items
If String.Equals(item.Tag.ToString(), fullPath, StringComparison.OrdinalIgnoreCase) Then
item.Selected = True
item.Focused = True
item.EnsureVisible()
Exit For
End If
Next
End Sub
Private Sub SelectListViewItemByPath(fullPath As String)- This defines a subroutine named
SelectListViewItemByPath. - It takes one input:
fullPath, which is the complete file or folder path you want to select in the ListView. - The goal is simple: find the matching item and highlight it.
For Each item As ListViewItem In lvFiles.Items- This starts a loop that goes through every item in the ListView (
lvFiles). itemrepresents the current ListViewItem being checked.- The loop continues until a match is found or all items have been checked.
If String.Equals(item.Tag.ToString(), fullPath, StringComparison.OrdinalIgnoreCase) Then- Each ListViewItem stores its full path inside its
.Tagproperty. - This line compares the item's stored path with the
fullPathwe’re searching for. StringComparison.OrdinalIgnoreCasemeans:- Compare the text exactly
- Ignore uppercase/lowercase differences
This matches how Windows treats file paths.
item.Selected = True- Marks the item as selected in the ListView.
- This highlights it visually.
item.Focused = True- Gives the item keyboard focus.
- This ensures:
- Arrow keys start from this item
- The dotted focus rectangle appears
- It behaves like the user clicked it
item.EnsureVisible()- Scrolls the ListView so the item is visible.
- If the item is off‑screen, the ListView automatically scrolls to bring it into view.
- This is essential for a smooth “Find Next” experience.
Exit For- Stops the loop immediately.
- No need to keep searching once the correct item is found.
End If
Next- Ends the
Ifblock and continues the loop if needed.
End Sub- Ends the subroutine.
The File Explorer supports a set of convenient keyboard shortcuts to speed up navigation and file operations. These shortcuts mirror familiar behaviors from traditional file managers, making the interface fast and intuitive.
| Shortcut | Action |
|---|---|
| Alt + ← (or Backspace) | Go back to the previous folder |
| Alt + → | Go forward to the next folder |
| Alt + ↑ | Move up one level (parent directory) |
| Ctrl + L (or Alt + D, F4) | Focus/select the address bar |
| F11 | Toggle full‑screen mode |
| Shortcut | Action |
|---|---|
| F2 | Rename the selected file or folder |
| Ctrl + Shift + N | Create a new folder |
| Ctrl + Shift + T | Create a new text file |
| Ctrl + O | Open the selected file or folder or start an open command |
| Ctrl + C | Copy selected items |
| Ctrl + V | Paste items |
| Ctrl + X | Cut selected items |
| Ctrl + A | Select all items |
| Ctrl + Shift + E | Expand the selected folder or drive |
| Ctrl + Shift + C | Collapse the selected folder or drive |
| Ctrl + D (or Delete) | Delete selected item to the Recycle Bin |
| Shortcut | Action |
|---|---|
| Ctrl + F | Start a search in the current folder |
| F3 | Select the next search result. |
| F5 | Refresh the current folder view |
This project is licensed under the MIT License. You are free to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the software, with the inclusion of the copyright notice and permission notice in all copies or substantial portions of the software.
To install and run the File Explorer application:
- Clone the repository:
git clone https://github.com/JoeLumbley/File-Explorer.git
- Open the solution in Visual Studio.
- Build the project and run it.
- Launch the application to access your file system.
- Use the tree view on the left to navigate through folders.
- The list view on the right displays the contents of the selected directory.
- Use the text box to enter commands or navigate directly to a path.
- Right-click on files or folders for additional options.
This project is inspired by traditional file explorers and aims to provide a simplified experience for managing files on Windows systems.
For more details, check the source code and documentation within the repository.