: C# 2008 Programmer

Building the Directory Tree and Displaying Images

Building the Directory Tree and Displaying Images

When the form is loaded, you first load the values of the application settings into the TextBox controls, and then display a node representing the root directory of the FTP server in the TreeView control:

private void Form1_Load(object sender, EventArgs e) {
try {
//---load the application settings values
// into the textbox controls---
txtFTPServer.Text = Properties.Settings.Default.FTP_SERVER;
txtUserName.Text = Properties.Settings.Default.UserName;
txtPassword.Text = Properties.Settings.Default.Password;
//---create the root node for the TreeView---
TreeNode node = new TreeNode();
node.ImageIndex = ico_CLOSE;
node.SelectedImageIndex = ico_OPEN;
node.Text = @"/";
//---add the root node to the control---
TreeView1.Nodes.Add(node);
//---add the dummy child node to the root node---
node.Nodes.Add("");
//---select the root node---
TreeView1.SelectedNode = node;
} catch (Exception ex) {
MessageBox.Show(ex.ToString());
}
}

You will always add a dummy node in the TreeView control after a node is created to ensure that the current node can be expanded to reveal subdirectories (even if there are none). This is shown in Figure 16-10.


Figure 16-10

When a node is expanded (by clicking on the + symbol), the TreeView1_BeforeExpand event is fired. You have to write code that checks to see if the current node is a leaf node (meaning that it is not a directory but a file). If it is a leaf node, exit the method. Otherwise, you need to display its subdirectories (if any).

You should also change the current node icon to "open" if the node is selected and "closed" if the node is not selected. Here's the code for expanding folders and displaying the proper icon at each node:

private void TreeView1_BeforeExpand(
object sender, TreeViewCancelEventArgs e) {
//---if leaf node (photo) then exit---
if (e.Node.ImageIndex == ico_PHOTO) return;
//---remove the dummy node and display the subdirectories and files---
try {
//---clears all the nodes and...---
e.Node.Nodes.Clear();
//---create the nodes again---
BuildDirectory(e.Node);
} catch (Exception ex) {
ToolStripStatusLabel1.Text = ex.ToString();
}
//---change the icon for this node to open---
if (e.Node.GetNodeCount(false) > 0) {
e.Node.ImageIndex = ico_CLOSE;
e.Node.SelectedImageIndex = ico_OPEN;
}
}

The BuildDirectory() function displays all the files and subdirectories within the current directory in the TreeView control. Before you look at the definition of the BuildDirectory() function, you define the GetDirectoryListing() function, whose main job is to request from the FTP server the directory listing of a specified path:

//---Get the file/dir listings and return them as a string array---
private string[] GetDirectoryListing(string path) {
try {
//---get the directory listing---
FtpWebResponse FTPResp = PerformWebRequest(
path, WebRequestMethod.ListDirectoryDetails);
//---get the stream containing the directory listing---
Stream ftpRespStream = FTPResp.GetResponseStream();
StreamReader reader =
new StreamReader(ftpRespStream, System.Text.Encoding.UTF8);
//---obtain the result as a string array---
string[] result = reader.ReadToEnd().Split(
Environment.NewLine.ToCharArray(),
StringSplitOptions.RemoveEmptyEntries);
FTPResp.Close();
return result;
} catch (Exception ex) {
MessageBox.Show(ex.ToString());
return null;
}
}

To view the directory listing of an FTP server, you make use of the PerformWebRequest() helper function, which is defined as follows:

private FtpWebResponse PerformWebRequest(
string path, WebRequestMethod method) {
//---display the hour glass cursor---
Cursor.Current = Cursors.WaitCursor;
FtpWebRequest ftpReq = (FtpWebRequest)WebRequest.Create(path);
switch (method) {
case WebRequestMethod.DeleteFile:
ftpReq.Method = WebRequestMethods.Ftp.DeleteFile;
break;
case WebRequestMethod.DownloadFile:
ftpReq.Method = WebRequestMethods.Ftp.DownloadFile;
break;
case WebRequestMethod.ListDirectoryDetails:
ftpReq.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
break;
case WebRequestMethod.MakeDirectory:
ftpReq.Method = WebRequestMethods.Ftp.MakeDirectory;
break;
case WebRequestMethod.RemoveDirectory:
ftpReq.Method = WebRequestMethods.Ftp.RemoveDirectory;
break;
}
ftpReq.Credentials = new NetworkCredential(
Properties.Settings.Default.UserName,
Properties.Settings.Default.Password);
FtpWebResponse ftpResp = (FtpWebResponse)ftpReq.GetResponse();
//---change back the cursor---
Cursor.Current = Cursors.Default;
return ftpResp;
}

The PerformWebRequest() function contains two parameters:

?A path representing the full FTP path

?A WebRequestMethod enumeration representing the type of request you are performing

In the PerformWebRequest() function, you perform the following:

?Create an instance of the FtpWebRequest class, using the WebRequest class's Create() method. Create() takes in a URI parameter (containing the full FTP path).

?Set the command to be sent to the FTP server, using the Method property of the FtpWebRequest object.

?Specify the login credential to the FTP server, using the NetWorkCredential class.

?Obtain the response from the FTP server, using the GetResponse() method from the FtpWebRequest class.

The PerformWebRequest() function returns a FtpWebResponse object.

Back in the GetDirectoryListing() function, after the call to PerformWebRequest() returns, you retrieve the stream containing the response data sent by the FTP server, using the GetResponseStream() method from the FtpWebResponse class. You then use a StreamReader object to read the directory listing:

//---Get the file/dir listings and return them as a string array---
private string[] GetDirectoryListing(string path) {
try {
//---get the directory listing---
FtpWebResponse FTPResp = PerformWebRequest(
path, WebRequestMethod.ListDirectoryDetails);
//---get the stream containing the directory listing---
Stream ftpRespStream = FTPResp.GetResponseStream();
StreamReader reader =
new StreamReader(ftpRespStream, System.Text.Encoding.UTF8);
//---obtain the result as a string array---
string[] result = reader.ReadToEnd().Split(
Environment.NewLine.ToCharArray(),
StringSplitOptions.RemoveEmptyEntries);
FTPResp.Close();
return result;
} catch (Exception ex) {
MessageBox.Show(ex.ToString());
return null;
}
}

The directory listing is split into a string array. The directory listings are separated by newline characters. If your FTP server is configured with an MS-DOS directory listing style (see Figure16-11), the directory listing will look something like this:

12-11-06 10:54PM 2074750 DSC00098.JPG
12-11-06 10:54PM 2109227 DSC00099.JPG
12-11-06 10:49PM<DIR> George
12-11-06 10:49PM<DIR> James
12-11-06 10:58PM<DIR> Wei-Meng Lee


Figure 16-11

Because all subdirectories have the <DIR> field, you can easily differentiate subdirectories from files in the BuildDirectory() function by looking for <DIR> in each line:

//---Build the directory in the TreeView control---
private void BuildDirectory(TreeNode ParentNode) {
string[] listing = GetDirectoryListing(
Properties.Settings.Default.FTP_SERVER + ParentNode.FullPath);
foreach (string line in listing) {
if (line == String.Empty) break;
TreeNode node = new TreeNode();
if (line.Substring(24, 5) == "<DIR>") {
//---this is a directory; create a new node to be added---
node.Text = line.Substring(39);
node.ImageIndex = ico_CLOSE;
node.SelectedImageIndex = ico_OPEN;
//---add the dummy child node---
node.Nodes.Add("");
ParentNode.Nodes.Add(node);
} else {
//---this is a normal file; create a new node to be added---
node.Text = line.Substring(39);
node.ImageIndex = ico_PHOTO;
node.SelectedImageIndex = ico_PHOTO;
ParentNode.Nodes.Add(node);
}
}
}

When a node is selected, you first obtain its current path and then display that path in the status bar if it is a folder. If it is an image node, download and display the photo, using the DownloadImage() function. All these are handled in the TreeView1_AfterSelect event. Here's the code:

private void TreeView1_AfterSelect(object sender, TreeViewEventArgs e) {
//---always ignore the first "/" char---
string FullPath =
Properties.Settings.Default.FTP_SERVER +
e.Node.FullPath.Substring(1).Replace("r", "");
//---display the current folder selected---
if (e.Node.ImageIndex != ico_PHOTO) {
ToolStripStatusLabel1.Text = FullPath;
return;
}
//---download image---
DownloadImage(FullPath);
}

The DownloadImage() function downloads an image from the FTP server and displays the image in a PictureBox control:

//---Download the image from the FTP server---
private void DownloadImage(string path) {
try {
ToolStripStatusLabel1.Text = "Downloading image..." + path;
Application.DoEvents();
//---download the image---
FtpWebResponse FTPResp =
PerformWebRequest(path, WebRequestMethod.DownloadFile);
//---get the stream containing the image---
Stream ftpRespStream = FTPResp.GetResponseStream();
//---display the image---
PictureBox1.Image = Image.FromStream(ftpRespStream);
FTPResp.Close();
ToolStripStatusLabel1.Text =
"Downloading image...complete(" + path + ")";
} catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}

To download an image file using FTP and then bind it to a PictureBox control:

?Call the PerformWebRequest() helper function you defined earlier.

?Retrieve the stream that contains response data sent from the FTP server, using the GetResponseStream() method from the FtpWebResponse class.

To set the PictureBox control to display the downloaded image, use the FromStream() method from the Image class to convert the response from the FTP server (containing the image) into an image.


: 1.054. /Cache: 3 / 1