Reputation: 29
I have a server hosted in my Linux PC. Now I am creating a FTP client with some specific tools to handle. Now I want to generate my a TreeView in my windows form. I have already generated a treeview but it takes too much to login cause listing all the directories and sub directories take big amount of time when the directories increase. I want to load only the first layer of directories then when user clicks on the expand ('+') button then it should populate the directories under that and like it. How this can be done? My current treeview code look like this
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Windows.Forms;
namespace GISFileManagerClient
{
public class TreeView
{
public FtpWebResponse PopulateDirectories(TreeNode parentNode,
string ftpRootPath,
string hostUsername,
string hostPassword,
FtpWebRequest request,
FtpWebResponse response
)
{
try
{
// ftp request for each directory list
request = (FtpWebRequest)WebRequest.Create(ftpRootPath);
request.Credentials = new NetworkCredential(hostUsername, hostPassword);
request.Method = WebRequestMethods.Ftp.ListDirectory;
request.KeepAlive = true;
response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
string directoryContents = reader.ReadToEnd();
string[] directories = directoryContents.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
List<string> modifiedDirectories = new List<string>();
foreach (string directory in directories)
{
// splitting directory name for refined folder
string[] parts = directory.Split('/');
// getting last string after '/' as that will be present directory "AWGSS/DG" will give DG
string modifiedDirectory = parts[parts.Length - 1];
// refined directories name to remove confusion
modifiedDirectories.Add(modifiedDirectory);
}
// converting list to string array before passing
string[] finalDirectories = modifiedDirectories.ToArray();
foreach (string directory in finalDirectories)
{
// creating node for each directory
Console.WriteLine($"directory looks like this: {directory}");
TreeNode node = new TreeNode(directory);
parentNode.Nodes.Add(node);
Console.WriteLine($"new stream looks like this: {ftpRootPath}/{Path.GetFileName(directory)}");
// condition to differentiate between file and directory
bool isDirectory = Path.GetFileName(directory).Contains(".");
if (isDirectory)
{
continue;
}
else
{
PopulateDirectories(node, $"{ftpRootPath}/{Path.GetFileName(directory)}", hostUsername, hostPassword, request, response);
}
}
reader.Close();
}
catch (WebException ex)
{
// Handle exception
// MessageBox.Show($"Error: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
Console.WriteLine($"Error: {ex.Message}");
}
return response;
}
}
}
Tried to populate treeview directories frequently.
Expecting to populate subs on user clicking on expand button, not before.
Upvotes: 1
Views: 49
Reputation: 202534
Implement the TreeView.BeforeExpand
event to populate the node only once the user expands it: https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.treeview.beforeexpand
You will also have to make sure the expand button shows even for nodes that were not visited yet. While technically the underlying Windows Tree-view control does allow that (see TVIF_CHILDREN
), this functionality does no seem to be exposed in WinForms. You will either have to implement that using P/Invoke (while it's doable, it's a lot of work, as the API is complex), or just add a fake child node to not-yet-populated nodes.
Related questions:
You should also consider populating the tree from a background thread, not to block the GUI thread. And that will actually allow you to populate whole tree on the background, not only once the user expands a node. But that's for another question.
Upvotes: 1