Question

How do I into recursive loops? First off, I want to loop out lists of folders and files, of course these files should be inside their respective folders and I'm gonna display the list on the web through HTML and CSS. I have a List<DirectoryInfo> and a List<FileInfo> for storing my folders and files.

I can do a basic foreach loop in my View like this:

@foreach (DirectoryInfo folder in ViewBag.folders)
    {
        <p>@folder.Name</p>
        foreach (FileInfo file in ViewBag.files)
        {
            if (folder.FullName == file.DirectoryName)
            { 
                <p class="file" data-url="@file.FullName.Substring(file.DirectoryName.IndexOf("Content"))" style="margin-left:20px;">@file.Name</p>
            }
        }
    }

And this works, it displays all folders and the files in their respective folders. However the issue that comes here is as you might have already guessed, subfolders. Currently all folders are in the same list, including subfolders.

I can do something like this

<ol class="tree">
    @{
        int i = 1;
        int subFolderi = 1;
    foreach (DirectoryInfo folder in ViewBag.folders)
    {
        <li>
        <label for="folder-@i">@folder.Name</label> <input type="checkbox" id="folder-@i" /> 
        <ol>
        @foreach (DirectoryInfo subFolder in ViewBag.folders)
        {
            if (folder.Name == subFolder.Parent.ToString())
            {
                <li>
                <label for="subfolder-@subFolderi">@subFolder.Name</label> <input type="checkbox" id="subfolder-@subFolderi" /> 
                <ol>
                @foreach (FileInfo file in ViewBag.files)
                {
                    if (subFolder.FullName == file.DirectoryName)
                    { 
                        <li class="file" data-url="@file.FullName.Substring(file.DirectoryName.IndexOf("Content"))">@file.Name</li>
                    }
                }
                </ol>
                </li>
            }
            subFolderi++;
        }
        @foreach (FileInfo file in ViewBag.files)
        {

            if (folder.FullName == file.DirectoryName)
            { 
                <li class="file" data-url="@file.FullName.Substring(file.DirectoryName.IndexOf("Content"))">@file.Name</li>
            }
        }
        </ol>
        </li>
        i++;
    }
    }
    </ol>

And it'll put the subfolders inside their parent folders, however this obviously only works for the first tier of subfolders, not the subfolders inside the subfolders. And it also display these subfolders twice, once inside their parent folder and one in the main folder list.

The question is then, am I supposed to make a recursive loop to keep getting the subfolders and their files inside the subfolders or should I do some sort of LINQ to combine everything before-hand to make the loop easier? Or is there a better way to do this? I prefer a clean way were I still have control over the HTML/CSS, so no jQuery plugins or ASP controls that uses a datasource and then creates everything automatically.

Working solution

<ol class="tree">
    @printFolder(ViewBag.contentFolder)
    </ol>

    @helper printFolder(DirectoryInfo folder)
    {
        <li>
            <label for="folder-@folder.Name">@folder.Name</label> <input type="checkbox" id="folder-@folder.Name" />
            <ol>
                    @foreach(DirectoryInfo subFolder in folder.GetDirectories())
                    {
                        @printFolder(subFolder)
                    }
                    @foreach(FileInfo file in folder.GetFiles())
                    {
                        @printFile(file)
                    }
            </ol>
        </li>
    }
    @helper printFile(FileInfo file)
    {
        <li class="file" data-url="@file.FullName.Substring(file.DirectoryName.IndexOf("Content"))">@file.Name</li>
    }
Was it helpful?

Solution 2

Can't you use the GetFiles() and GetDirectories() of the DirectoryInfo to print the whole file tree? Something like:

foreach (var folder in folders)
  PrintFolder(folder);

PrintFolder(DirectoryInfo folder)
{
  // ... print folder name here ...

  foreach(var subFolder in folder)
     PrintFolder(folder);

  foreach(var file in folder.GetFiles())
     PrintFile(file);

}

PrintFile(FileInfo file)
{
  // ... print file name here ... 
}

OTHER TIPS

I would use a DisplayTemplate for a folder. This would render all folders inside it using itself as a template, thus doing the recursion.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top