Exclude displaying certain folders and subfolders in a Treeview - c#

on one of my drives I have a folder structure ex
d:\
123
Code
testfile.cs
Database
Backup.mdb
Requirements
Sprint1.xls
234
20132305
20132205
20132105
Database
I would like to in my treeview show the following
d:\
123
Code
testfile.cs
Database
Backup.mdb
234
Database
i.e only show folders and subfolders for "code" and "database"
Here is the code to load the treeview
folderLst = {"123","234"}
private void PopulateTreeView()
{
TreeNode rootNode;
foreach (string f in folderLst)
{
DirectoryInfo info = new DirectoryInfo(#"d:\");
if (info.Exists)
{
rootNode = new TreeNode(info.Name);
rootNode.Tag = info;
GetDirectories(info.GetDirectories(), rootNode);
treeView1.Nodes.Add(rootNode);
}
}
}
private void GetDirectories(DirectoryInfo[] subDirs, TreeNode nodeToAddTo)
{
TreeNode aNode;
DirectoryInfo[] subSubDirs;
foreach (DirectoryInfo subDir in subDirs)
{
aNode = new TreeNode(subDir.Name, 0, 0);
aNode.Tag = subDir;
subSubDirs = subDir.GetDirectories();
if (subSubDirs.Length != 0)
{
GetDirectories(subSubDirs, aNode);
}
nodeToAddTo.Nodes.Add(aNode);
}
}
any help is appreciated

You have the following code
foreach (DirectoryInfo subDir in subDirs)
{
aNode = new TreeNode(subDir.Name, 0, 0);
aNode.Tag = subDir;
subSubDirs = subDir.GetDirectories();
if (subSubDirs.Length != 0)
{
GetDirectories(subSubDirs, aNode);
}
nodeToAddTo.Nodes.Add(aNode);
}
You can modify it to not add the desired folders
foreach (DirectoryInfo subDir in subDirs)
{
if(subDir.Name.Contains("Code") || subDir.Name.Contains("Database"))
{
aNode = new TreeNode(subDir.Name, 0, 0);
aNode.Tag = subDir;
subSubDirs = subDir.GetDirectories();
if (subSubDirs.Length != 0)
{
GetDirectories(subSubDirs, aNode);
}
nodeToAddTo.Nodes.Add(aNode);
}
}

Related

How to skip the creating the root node on a treeview?

How would you modify this code to skip creating the root node and create only the other nodes?
void ListDirectory(TreeView treeView, string path)
{
treeView.Nodes.Clear();
var rootDirectoryInfo = new DirectoryInfo(path);
treeView.Nodes.Add(CreateDirectoryNode(rootDirectoryInfo));
}
TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
var directoryNode = new TreeNode(directoryInfo.Name);
foreach (var directory in directoryInfo.GetDirectories())
{
directoryNode.Nodes.Add(CreateDirectoryNode(directory));
}
return directoryNode;
}
Like this:
void ListDirectory(TreeView treeView, string path)
{
treeView.Nodes.Clear();
var rootDirectoryInfo = new DirectoryInfo(path);
foreach (var directory in rootDirectoryInfo.GetDirectories())
{
treeView.Nodes.Add(CreateDirectoryNode(directory));
}
}
TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
var directoryNode = new TreeNode(directoryInfo.Name);
foreach (var directory in directoryInfo.GetDirectories())
{
directoryNode.Nodes.Add(CreateDirectoryNode(directory));
}
return directoryNode;
}

Populate TreeView with non-Empty Folders

private void ListDirectory(TreeView treeView, string path)
{
treeView.Nodes.Clear();
var rootDirectoryInfo = new DirectoryInfo(path);
treeView.Nodes.Add(CreateDirectoryNode(rootDirectoryInfo));
}
private static TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
var directoryNode = new TreeNode(directoryInfo.Name);
foreach (var directory in directoryInfo.GetDirectories())
directoryNode.Nodes.Add(CreateDirectoryNode(directory));
foreach (var file in directoryInfo.GetFiles().Where(s => s.Extension == ".jpg"))
directoryNode.Nodes.Add(new TreeNode(file.Name));
return directoryNode;
}
using this code I can list all jpg files and folders from a given directory. But it will list empty folders of jpg files too. How can I avoid it?
The solution is to check whether there are any files on the return from the recursion, then add it if there are.
foreach (var directory in directoryInfo.GetDirectories())
{
TreeNode subNode = CreateDirectoryNode(directory);
if (subNode.Nodes.Count > 0)
directoryNode.Nodes.Add(CreateDirectoryNode(directory));
}
Since you're doing a depth first search the nodes will effectively be culled from the leaf up to the root if there aren't any files.
You need to check if the number of sub directories is zero and the number of files in the directory is zero. If this is the case, you should not create the node.
One way to do this is to return null from the CreateDirectoryNode method if the directory does not meet the specification. And then only add sub nodes that are not null.
Consider this code:
private void ListDirectory(TreeView treeView, string path)
{
treeView.Nodes.Clear();
var rootDirectoryInfo = new DirectoryInfo(path);
var tree_node = CreateDirectoryNode(rootDirectoryInfo);
if (tree_node != null)
treeView.Nodes.Add(tree_node);
}
//This method will return null of the specified directory does not have sub folders or JPG files
private static TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
//Obtain all sub directories
var sub_directories = directoryInfo.GetDirectories();
//Obtain all JPG files
var jpeg_files =
directoryInfo.GetFiles()
.Where(s => s.Extension.Equals(".jpg", StringComparison.OrdinalIgnoreCase))
.ToArray();
//If the above arrays are empty, return null
if (sub_directories.Length == 0 && jpeg_files.Length == 0)
return null;
var directoryNode = new TreeNode(directoryInfo.Name);
foreach (var directory in sub_directories)
{
var sub_node = CreateDirectoryNode(directory);
if(sub_node != null) //Only add sub nodes if they are not null
directoryNode.Nodes.Add(sub_node);
}
foreach (var file in jpeg_files)
directoryNode.Nodes.Add(new TreeNode(file.Name));
return directoryNode;
}

c# How to dynamically add tree nodes during runtime

I'm trying to add nodes dynamically during run-time to an existing tree-view emulating windows explorer. I have code that works, but because of the amount of recursion that takes place it takes 2-3 minutes to check for all of the files on the c: drive and create the tree.
What I would like to do instead is something like this:
-NodeClickEvent-
if has children { do nothing }
else { add children and grandchildren to selected node }
This is so that it does not have to load the entire tree, but instead loads a couple layers at a time on a per-click basis.
http://www.codeproject.com/Articles/26288/Simplifying-the-WPF-TreeView-by-Using-the-ViewMode
Look at demo 2 in the same article
when creating a treeview item, attach a dummy object
On expansion of each treeview item, delete the dummy child if it is in and add actual children if at all it has.
Its very clearly explained in the above quoted article
IF you are not very familiar wtih tree view , then you can first take this tutorial http://www.dotnetperls.com/treeview
and this tutorial describes how to use treelist.
And these following links explain that what you are looking for
http://msdn.microsoft.com/en-us/library/aa984278%28VS.71%29.aspx
http://msdn.microsoft.com/en-us/library/aa645739%28v=vs.71%29.aspx
Thanks for all the input; I think I finally figured out how to do what I was looking for here: An unhandled exception of type 'System.NullReferenceException' occurring when clicking TreeNode
My Code is:
public Form1()
{
InitializeComponent();
this.treeView1.NodeMouseClick += new TreeNodeMouseClickEventHandler(this.treeView1_NodeMouseClick);
PopulateTreeView();
}
private void PopulateTreeView()
{
TreeNode rootNode;
DirectoryInfo info = new DirectoryInfo(#"c:\\");
if (info.Exists)
{
rootNode = new TreeNode(info.Name);
rootNode.Tag = info;
GetDirectories(info.GetDirectories(), rootNode);
treeView1.Nodes.Add(rootNode);
}
}
private void GetDirectories(DirectoryInfo[] subDirs, TreeNode nodeToAddTo)
{
TreeNode aNode;
//DirectoryInfo[] subSubDirs;
foreach (DirectoryInfo subDir in subDirs)
{
aNode = new TreeNode(subDir.Name, 0, 0);
aNode.Tag = subDir;
aNode.ImageKey = "folder";
/* try
{
subSubDirs = subDir.GetDirectories();
if (subSubDirs.Length != 0)
{
GetDirectories2(subSubDirs, aNode);
}
}
catch (System.UnauthorizedAccessException)
{
subSubDirs = new DirectoryInfo[0];
}*/
nodeToAddTo.Nodes.Add(aNode);
}
}
void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
try
{
DirectoryInfo d = new DirectoryInfo(#e.Node.FullPath);
if (e.Node.Nodes.Count > 0) { /*Do Nothing.*/ } else { GetDirectories(d.GetDirectories(), e.Node); e.Node.Expand(); }
TreeNode newSelected = e.Node;
listView1.Items.Clear();
DirectoryInfo nodeDirInfo = (DirectoryInfo)newSelected.Tag;
ListViewItem.ListViewSubItem[] subItems;
ListViewItem item = null;
foreach (DirectoryInfo dir in nodeDirInfo.GetDirectories())
{
item = new ListViewItem(dir.Name, 0);
subItems = new ListViewItem.ListViewSubItem[]
{new ListViewItem.ListViewSubItem(item, "Directory"),
new ListViewItem.ListViewSubItem(item,
dir.LastAccessTime.ToShortDateString())};
item.SubItems.AddRange(subItems);
listView1.Items.Add(item);
}
foreach (FileInfo file in nodeDirInfo.GetFiles())
{
item = new ListViewItem(file.Name, 1);
subItems = new ListViewItem.ListViewSubItem[]
{ new ListViewItem.ListViewSubItem(item, "File"),
new ListViewItem.ListViewSubItem(item,
file.LastAccessTime.ToShortDateString())};
item.SubItems.AddRange(subItems);
listView1.Items.Add(item);
}
listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
}
catch (Exception ex)
{
if (ex is System.NullReferenceException || ex is System.UnauthorizedAccessException)
{
// Do Nothing.
}
}
}`

Creating xml from directory structure

I have a directory with files and sub directories with files and want to create xml from them. here is my folder structure:
C:\inputdata folder contains:
C:\inputdata\file1.txt
C:\inputdata\picture1.jpg
C:\inputdata\subfolder\picture2.jpg
C:\inputdata\subfolder\file2.txt
C:\inputdata\subfolder\anotherfolder \file3.txt
C:\inputdata\anotherfolder\
and i want to generate this xml file:
<?xml version="1.0" encoding="UTF-8"?>
<serverfiles>
<file name="picture1.jpg"/>
<file name="file1.txt"/>
<folder name="subfolder">
<file name="picture2.jpg"/>
<file name="file2.txt"/>
<folder name="anotherfolder">
<file name="file3.txt"/>
</folder>
</folder>
<folder name="anotherfolder">
</folder>
</serverfiles>
I have written following console app but i have two problems.
this produces the attached screenshot xml which is not exactly as above xml in terms of structure.
is there a way I could sort this with the name attribute with my code.
can someone please point me to right direction of how to do this please:
private const string folderLocation = #"c:\inputdata";
static void Main(string[] args)
{
DirectoryInfo dir = new DirectoryInfo(folderLocation);
var doc = new XDocument(CREATEXML(dir));
Console.WriteLine(doc.ToString());
Console.Read();
}
private static XElement CREATEXML(DirectoryInfo dir)
{
//get directories
var xmlInfo = new XElement("serverfiles", new XAttribute("name", dir.Name));
//get all the files first
foreach(var file in dir.GetFiles())
{
xmlInfo.Add(new XElement("file", new XAttribute("name", file.Name)));
}
//get subdirectories
foreach(var subDir in dir.GetDirectories())
{
xmlInfo.Add(CREATEXML(subDir));
}
return xmlInfo;
}
Nearly there: just some small edits to your code are what you need.
private const string folderLocation = #"c:\inputdata";
static void Main(string[] args)
{
DirectoryInfo dir = new DirectoryInfo(folderLocation);
// makes everything wrapped in an XElement called serverfiles.
// Also a declaration as specified (sorry about the standalone status:
// it's required in the XDeclaration constructor)
var doc = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"),
CREATEXML(dir));
Console.WriteLine(doc.ToString());
Console.Read();
}
private static XElement CREATEXML(DirectoryInfo dir, bool writingServerFiles = true)
{
//get directories
var xmlInfo = new XElement(writingServerFiles ? "serverfiles" : "folder", writingServerFiles ? null : new XAttribute("name", dir.Name)); //fixes your small isue (making the root serverfiles and the rest folder, and serverfiles not having a name XAttribute)
//get all the files first
foreach(var file in dir.GetFiles())
{
xmlInfo.Add(new XElement("file", new XAttribute("name", file.Name)));
}
//get subdirectories
foreach(var subDir in dir.GetDirectories())
{
xmlInfo.Add(CREATEXML(subDir), false);
}
return xmlInfo;
}
You can add one more method that will handle subdirectories
private static XElement CreateXML(DirectoryInfo dir)
{
var xmlInfo = new XElement("serverfiles");
//get all the files first
foreach (var file in dir.GetFiles())
{
xmlInfo.Add(new XElement("file", new XAttribute("name", file.Name)));
}
//get subdirectories
foreach (var subDir in dir.GetDirectories())
{
xmlInfo.Add(CreateSubdirectoryXML(subDir));
}
return xmlInfo;
}
private static XElement CreateSubdirectoryXML(DirectoryInfo dir)
{
//get directories
var xmlInfo = new XElement("folder", new XAttribute("name", dir.Name));
//get all the files first
foreach (var file in dir.GetFiles())
{
xmlInfo.Add(new XElement("file", new XAttribute("name", file.Name)));
}
//get subdirectories
foreach (var subDir in dir.GetDirectories())
{
xmlInfo.Add(CreateSubdirectoryXML(subDir));
}
return xmlInfo;
}
EDIT:
Added sorting:
private static XElement CreateXML(DirectoryInfo dir)
{
var xmlInfo = new XElement("serverfiles");
//get all the files first
foreach (var file in dir.GetFiles())
{
xmlInfo.Add(new XElement("file", new XAttribute("name", file.Name)));
}
//get subdirectories
var subdirectories = dir.GetDirectories().ToList().OrderBy(d => d.Name);
foreach (var subDir in subdirectories)
{
xmlInfo.Add(CreateSubdirectoryXML(subDir));
}
return xmlInfo;
}
private static XElement CreateSubdirectoryXML(DirectoryInfo dir)
{
//get directories
var xmlInfo = new XElement("folder", new XAttribute("name", dir.Name));
//get all the files first
foreach (var file in dir.GetFiles())
{
xmlInfo.Add(new XElement("file", new XAttribute("name", file.Name)));
}
//get subdirectories
var subdirectories = dir.GetDirectories().ToList().OrderBy(d => d.Name);
foreach (var subDir in subdirectories)
{
xmlInfo.Add(CreateSubdirectoryXML(subDir));
}
return xmlInfo;
}
I think this solution can be better
//get directories
var xmlInfo = new XElement("folder",
new XElement("name", dir.Name),
new XElement("lastModify", dir.LastWriteTime),
new XElement("Attributes", dir.Attributes));
//get subdirectories
foreach (var subDir in dir.GetDirectories())
{
xmlInfo.Add(CREATEXML(subDir));
}
//get all the files
foreach (var file in dir.GetFiles())
{
xmlInfo.Add(new XElement("File",
new XElement("name", file.Name),
new XElement("size", file.Length),
new XElement("lastModify", file.LastWriteTime),
new XElement("Attributes", file.Attributes.ToString())));
}
return xmlInfo;

How do I return a list of my folders with the files inside?

I am wondering how can I return the list of my folders with the files inside.
Because I can't return both of the list...and can't put both types in the list.
public List<DirectoryInfo> GetTopFolders()
{
List<DirectoryInfo> Folders = new List<DirectoryInfo>();
List<FileInfo> Files = new List<FileInfo>();
System.IO.DirectoryInfo di = new System.IO.DirectoryInfo("C://inetpub//wwwroot//Files//");
di.GetDirectories();
System.IO.FileInfo[] fiArr = di.GetFiles();
foreach (DirectoryInfo t in di.GetDirectories())
{
Folders.Add(t);
foreach (FileInfo f in di.GetFiles())
{
Files.Add(f);
}
}
return Folders;
}
This is the code I am actually using.
Well, both FileInfo and DirectoryInfo inherit from FileSystemInfo. So you could maintain a list of that type instead and return the whole lot together:
public List<FileSystemInfo> GetTopFoldersAndFiles()
{
List<FileSystemInfo> FilesAndFolders = new List<FileSystemInfo>();
System.IO.DirectoryInfo di = new System.IO.DirectoryInfo("C://inetpub//wwwroot//Files//");
di.GetDirectories();
System.IO.FileInfo[] fiArr = di.GetFiles();
foreach (DirectoryInfo t in di.GetDirectories())
{
FilesAndFolders.Add(t);
foreach (FileInfo f in di.GetFiles())
{
FilesAndFolders.Add(f);
}
}
return FilesAndFolders;
}
Of course you might need some conditional handling in the code where you make use of this object based on each item's type.
You could use a two-tuple. See Tuple.Create on msdn
public Tuple<List<DirectoryInfo>,List<FileInfo>> GetTopFolders()
{
List<DirectoryInfo> Folders = new List<DirectoryInfo>();
List<FileInfo> Files = new List<FileInfo>();
/* All your other code here */
/* Removed for brevity*/
foreach (DirectoryInfo t in di.GetDirectories())
{
Folders.Add(t);
foreach (FileInfo f in di.GetFiles())
{
Files.Add(f);
}
}
return Tuple.Create(Folders, Files);
}
You use it like this:
var fileAndFolders = GetTopFolders()
fileAndFolders.Item1 //will be your folders of type List<DirectoryInfo>
fileAndFolders.Item2 //will be your folders of type List<FileInfo>
You can use a Dictionary<DirectoryInfo, List<FileInfo>>:
private Dictionary<DirectoryInfo, List<FileInfo>> GetTopFolders()
{
Dictionary<DirectoryInfo, List<FileInfo>> r = new Dictionary<DirectoryInfo, List<FileInfo>>();
DirectoryInfo di = new DirectoryInfo("C://inetpub//wwwroot//Files//");
di.GetDirectories();
r.Add(di, di.GetFiles().ToList());
foreach (DirectoryInfo t in di.GetDirectories())
{
r.Add(t, t.GetFiles().ToList());
}
return r;
}
then you can list your folders and files like this:
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<DirectoryInfo, List<FileInfo>> item in GetTopFolders())
{
sb.AppendLine(item.Key.FullName);
foreach (FileInfo file in item.Value)
{
sb.AppendLine("\t" + file.Name);
}
}
Console.WriteLine(sb.ToString());

Categories

Resources