Created
October 28, 2015 20:17
-
-
Save scionwest/100fd9e78d44b742dc5d to your computer and use it in GitHub Desktop.
This file contains 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; } | |
public IEnumerable<INode> Search(string filename) | |
{ | |
var searchResults = new List<INode>(); | |
foreach(INode node in this.Children) | |
{ | |
var directory = node as DirectoryNode; | |
if (directory != null) | |
{ | |
searchResults.AddRange(directory.Search(filename)); | |
} | |
if (node.Name.Contains(filename)) | |
{ | |
searchResults.Add(node); | |
} | |
} | |
return searchResults; | |
} | |
/// <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 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 searchString; | |
public string SearchContent | |
{ | |
get | |
{ | |
return this.searchString; | |
} | |
set | |
{ | |
this.searchString = value; | |
this.OnPropertyChanged(); | |
this.Filter(); | |
} | |
} | |
private void Filter() | |
{ | |
var searchResults = new List<INode>(); | |
foreach(INode node in this.RootNodes) | |
{ | |
Directory folder = node as DirectoryNode; | |
if (folder != null) | |
{ | |
searchResults.AddRange(folder.Search(this.SearchContent)); | |
} | |
if (node.Name.Contains(this.SearchContent)) | |
{ | |
searchResults.Add(node); | |
} | |
} | |
this.RootNodes = new ObservableCollection<INode>(searchResults); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment