Last active
July 5, 2017 14:18
-
-
Save JokerMartini/8796f5bfe73f0b6e5822 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Collections.ObjectModel; | |
using System.ComponentModel; | |
using System.IO; | |
using System.Linq; | |
using System.Runtime.CompilerServices; | |
using System.Threading.Tasks; | |
namespace DirectoryTree | |
{ | |
public class DirectoryNode : INode, INotifyPropertyChanged | |
{ | |
private ObservableCollection<INode> children; | |
public DirectoryNode(DirectoryInfo directoryInfo) | |
{ | |
this.Directory = directoryInfo; | |
this.Children = new ObservableCollection<INode>(); | |
} | |
public DirectoryNode(DirectoryInfo directoryInfo, DirectoryNode parent) : this(directoryInfo) | |
{ | |
this.Parent = parent; | |
} | |
public event PropertyChangedEventHandler PropertyChanged; | |
/// <summary> | |
/// Gets the name of the folder associated with this node. | |
/// </summary> | |
public string Name => this.Directory.Name; | |
/// <summary> | |
/// Gets the path to the directory associated with this node. | |
/// </summary> | |
public string Path => this.Directory?.FullName; | |
/// <summary> | |
/// Gets the parent directory for this node. | |
/// </summary> | |
public DirectoryNode Parent { get; } | |
/// <summary> | |
/// Gets the directory that this node represents. | |
/// </summary> | |
public DirectoryInfo Directory { get; } | |
/// <summary> | |
/// Gets or sets the children nodes that this directory node can have. | |
/// </summary> | |
public ObservableCollection<INode> Children | |
{ | |
get | |
{ | |
return this.children; | |
} | |
set | |
{ | |
this.children = value; | |
this.OnPropertyChanged(); | |
} | |
} | |
public bool IsFavorite { get; set; } | |
/// <summary> | |
/// Scans the current directory and creates a new collection of children nodes. | |
/// The Children nodes collection can be filled with EmptyFolderNode, FileNode or DirectoryNode instances. | |
/// The Children collection will always have at least 1 element within it. | |
/// </summary> | |
public Task BuildChildrenNodes(bool buildAllChildrenNodes = false) | |
{ | |
// Get all of the folders and files in our current directory. | |
FileInfo[] filesInDirectory = null; | |
DirectoryInfo[] directoriesWithinDirectory = null; | |
try | |
{ | |
filesInDirectory = this.Directory.GetFiles(); | |
directoriesWithinDirectory = this.Directory.GetDirectories(); | |
} | |
catch(UnauthorizedAccessException) | |
{ | |
return Task.FromResult(0); | |
} | |
// Convert the folders and files into Directory and File nodes and add them to a temporary collection. | |
var childrenNodes = new List<INode>(); | |
IEnumerable<DirectoryNode> directoryNodes = directoriesWithinDirectory.Select(dir => new DirectoryNode(dir, this)); | |
childrenNodes.AddRange(directoryNodes); | |
childrenNodes.AddRange(filesInDirectory.Select(file => new FileNode(this, file))); | |
if (childrenNodes.Count == 0) | |
{ | |
// If there are no children directories or files, we setup the Children collection to hold | |
// an single node that represents an empty directory. | |
this.Children = new ObservableCollection<INode>(new List<INode> { new EmptyFolderNode(this) }); | |
return Task.FromResult(0); | |
} | |
this.Children = new ObservableCollection<INode>(childrenNodes); | |
// If we don't want to lazily load our children, we must pre-load them all. | |
if (buildAllChildrenNodes) | |
{ | |
// return our running async process. | |
return Task.Run(() => | |
{ | |
foreach (DirectoryNode directory in this.Children.OfType<DirectoryNode>()) | |
{ | |
directory.BuildChildrenNodes(true); | |
} | |
}); | |
} | |
return Task.FromResult(0); | |
} | |
public IEnumerable<INode> GetFavorites() | |
{ | |
var favorites = new List<INode>(); | |
if (this.IsFavorite) | |
{ | |
favorites.Add(this); | |
} | |
// Get all of the FileNodes in our Children collection that have the IsFavorite bool set to true, and add them | |
// to the favorites collection. | |
favorites.AddRange(this.Children.OfType<FileNode>().Where(fileNode => fileNode.IsFavorite)); | |
// Use some nested recursion to loop through each directory in our children, and have those DirectoryNode's return to us their | |
// collection of favorites. | |
foreach(DirectoryNode directory in this.Children.OfType<DirectoryNode>()) | |
{ | |
favorites.AddRange(directory.GetFavorites()); | |
} | |
return favorites; | |
} | |
private void OnPropertyChanged([CallerMemberName] string propertyName = "") | |
{ | |
var handler = this.PropertyChanged; | |
if (handler == null) | |
{ | |
return; | |
} | |
handler(this, new PropertyChangedEventArgs(propertyName)); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private string searchText; | |
public string SearchText | |
{ | |
get | |
{ | |
return this.searchText; | |
} | |
set | |
{ | |
this.searchText = value; | |
this.OnPropertyChanged(); | |
this.GetDisplayNodes(); | |
} | |
} | |
private bool enableFavorites; | |
public bool EnableFavorites | |
{ | |
get | |
{ | |
return this.enableFavorites; | |
} | |
set | |
{ | |
this.enableFavorites = value; | |
this.GetDisplayNodes(); | |
} | |
} | |
public void GetDisplayNodes() | |
{ | |
// If filtering is enabled, then we must start filtering. | |
if (!this.EnableFavorites) | |
{ | |
// If we are not filtering, then we just reset our root nodes to the original collection. | |
this.RootNodes = this.initialRootCollection; | |
return; | |
} | |
var favorites = new List<INode>(); | |
// Creates our collection of favorite directories by filtering out all of our nested directories. | |
foreach (DirectoryNode node in this.RootNodes.OfType<DirectoryNode>()) | |
{ | |
favorites.AddRange(node.GetFavorites()); | |
} | |
// Add any favorite file nodes that might have been in our root node collection. | |
// Usually there wouldn't be, but we do this to be safe anyway. | |
favorites.AddRange(this.RootNodes.OfType<FileNode>().Where(fileNode => fileNode.IsFavorite)); | |
// Replace our root nodes with the filtered results. | |
this.RootNodes = favorites; | |
return; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment