Click here to Skip to main content
13,141,576 members (53,046 online)
Click here to Skip to main content
Add your own
alternative version

Stats

16.7K views
1.2K downloads
13 bookmarked
Posted 8 Jan 2012
CPL

Silverlight File Manager

, 8 Jan 2012
Rate this:
Please Sign up or sign in to vote.
The Silverlight File Manager on the ListBox control based universal server handler may be working on the ASP .NET WebForms and MVC projects. All requests are sent asynchronously via helper class.
Silverlight File Manager

Introduction

Silverlight applications have no direct access to the file system of server. To gain access to the server file system needs to be done the proxy (gateway) page.

I created a gateway class for processing requests. The class can be used in the ASP .NET WebForm and ASP.NET MVC projects.

File Manager is created as custom control based on the ListBox. The control has a method for sending requests to the server.

All requests are sent asynchronously via helper class. The helper class is optimized for File Manager, but it can be easily modified for other purposes.

Data exchange is carried out in the JSON. Is it optimal for traffic volume.

Server

Gateway class for processing requests created on the Class Library project.

The class has a main method - GetResult. The method for processing requests returns a JSON string.

Requests data are taken from HttpContext.Current.Request class. For it, I created a helper variable - Request, and also Server.

HttpRequest Request = HttpContext.Current.Request;
HttpServerUtility Server = HttpContext.Current.Server;

Server can only handle POST requests. Request parameters are available in the Form collection.

Server will handle the six operations:

  • check - check file name
  • upload - upload and save file on the server
  • newdir - create a new directory
  • delete - delete file or directory
  • rename - change name of the file or directory
  • get (default) - get file and directories list

Name of the operation will be contained in the parameter cmd.

string cmd = "";
if (!String.IsNullOrEmpty(Request.Form["cmd"])) { cmd = Request.Form["cmd"].ToLower(); }

The root directory name contains a _Root variable. The client must pass a relative path on the path field.

string _Root = ""; // empty - server root directory
string path = "";
if (!String.IsNullOrEmpty(Request.Form["path"])) 
	{ path = Request.Form["path"]; } else { path = "/"; }
if (!path.EndsWith("/")) path += "/";

Before executing the operation (cmd), the server must verify the existence of a directory.

DirectoryInfo DI = new DirectoryInfo
			(Server.MapPath(String.Format("~/{0}{1}", _Root, path)));
if (!DI.Exists)
{
  result = GetError(String.Format("Error. The directory \"{0}\" not found.", 
		String.Format("~/{0}{1}", _Root, path)));
  return result.ToString();
}

I did not create verification of the user authorization and access, but you can create it.

Server returns JSON string. I created two helper functions for it. First - GetError return JSON object with error message. Second - GetJsonString converting object to JSON.

private StringBuilder GetError(string msg)
{
  return GetJsonString(new { stat = "err", msg = msg });
}

private StringBuilder GetJsonString(object source)
{
  StringBuilder result = new StringBuilder();
  JavaScriptSerializer myJSON = new JavaScriptSerializer();
  myJSON.Serialize(source, result);
  return result;
}

I used anonymous types with next properties:

  • stat - server response code: ok - ok, err - error
  • msg - error message, if stat = err
  • allowUp - has top-level directory (only for file list requests)
  • data - array of files and directories (only for file list requests):
    • name - file or directory name
    • size - file size (only for files)
    • type - item type: 0 - directory, 1 - file
    • url - file URL
public class Gateway
{
  private string _Root = "Custom"; // root directory

  public Gateway() { }

  public string GetResult()
  {
    if (HttpContext.Current == null) throw new Exception("HTTP request is required.");

    HttpRequest Request = HttpContext.Current.Request;
    HttpServerUtility Server = HttpContext.Current.Server;

    StringBuilder result = new StringBuilder();

    try
    {
      // ...
      // here you can make authorization
      // ..

      string cmd = "", path = "";
      if (!String.IsNullOrEmpty(Request.Form["cmd"])) 
		{ cmd = Request.Form["cmd"].ToLower(); }
      if (!String.IsNullOrEmpty(Request.Form["path"])) 
		{ path = Request.Form["path"]; } else { path = "/"; }
      if (!path.EndsWith("/")) path += "/";
        
      DirectoryInfo DI = new DirectoryInfo
		(Server.MapPath(String.Format("~/{0}{1}", _Root, path)));
      if (!DI.Exists)
      {
        result = GetError(String.Format("Error. 
        The directory \"{0}\" not found.", String.Format("~/{0}{1}", _Root, path)));
        return result.ToString();
      }

      if (cmd == "check")
      {
        #region check file name
        if (File.Exists(Path.Combine(DI.FullName, Request.Form["name"])))
        {
          result = GetJsonString(new { stat = "err", msg = String.Format
          ("Sorry, file \"{0}\" is exists on the directory 
		\"{1}\".", Request.Form["name"], path) });
        }
        else
        {
          result = GetJsonString(new { stat = "ok" });
        }
        #endregion
      }
      else if (cmd == "upload")
      {
        #region save file
        if (Request.Files["file1"] == null || Request.Files["file1"].ContentLength <= 0)
        {
          result = GetError("Error. File is required.");
        }
        else
        {
          // check file name
          if (File.Exists(Path.Combine(DI.FullName, Request.Files["file1"].FileName)))
          { 
            result = GetJsonString(new { stat = "err", msg = String.Format
            ("Sorry, file \"{0}\" is exists on the directory \"{1}\".", 
            Request.Files["file1"].FileName, path) });
          }
          else
          { 
            // save
            using (FileStream fs = System.IO.File.Create
            (Path.Combine(DI.FullName, Request.Files["file1"].FileName)))
            {
              byte[] buffer = new byte[4096];
              int bytesRead;
              while ((bytesRead = Request.Files["file1"].
		InputStream.Read(buffer, 0, buffer.Length)) != 0)
              {
                fs.Write(buffer, 0, bytesRead);
              }
            }
            result = GetJsonString(new { stat = "ok" });
          }
        }
        #endregion
      }
      else if (cmd == "newdir")
      {
        #region create a new directory
        if (String.IsNullOrEmpty(Request.Form["name"]))
        {
          result = GetError("Error. Directory name is required.");
        }
        else
        {
          // check name
          DirectoryInfo d = new DirectoryInfo(Path.Combine
		(DI.FullName, Request.Form["name"]));
          if (d.Exists)
          {
            result = GetError("Sorry, directory is exists.");
          }
          else
          {
            // create directory
            d.Create();
            // is ok
            result = GetJsonString(new { stat = "ok" });
          }
        }
        #endregion
      }
      else if (cmd == "delete")
      {
        #region delete file/directory
        if (String.IsNullOrEmpty(Request.Form["name"]))
        {
          result = GetError("Error. Name is required.");
        }
        else
        {
          if (File.GetAttributes(Path.Combine(DI.FullName, 
		Request.Form["name"])) == FileAttributes.Directory)
          {
            // is directory, 
            Directory.Delete(Path.Combine(DI.FullName, Request.Form["name"]), true);
          }
          else
          {
            // is file
            File.Delete(Path.Combine(DI.FullName, Request.Form["name"]));
          }
          result = GetJsonString(new { stat = "ok" });
        }
        #endregion
      }
      else if (cmd == "rename")
      {
        #region rename file/directory
        string oldName = Request.Form["oldName"], newName = Request.Form["newName"];
        if (String.IsNullOrEmpty(oldName) || String.IsNullOrEmpty(newName))
        {
          result = GetError("Error. Name is required.");
        }
        else
        {
          if (newName != oldName)
          {
            if (File.GetAttributes(Path.Combine(DI.FullName, 
			oldName)) == FileAttributes.Directory)
            {
              // rename directory
              Directory.Move(Path.Combine(DI.FullName, oldName), 
			Path.Combine(DI.FullName, newName));
            }
            else
            {
              // rename file
              File.Move(Path.Combine(DI.FullName, oldName), 
			Path.Combine(DI.FullName, newName));
            }
          }
          result  = GetJsonString(new { stat = "ok" });
        }
        #endregion
      }
      else
      {
        #region file list
        ArrayList files = new ArrayList();
        // dicrectories
        foreach (DirectoryInfo d in DI.GetDirectories())
        {
          files.Add(new
          {
            name = d.Name,
            size = 0,
            type = 0, // type = 0 - is directory
            url = String.Format("http://{0}/{1}{2}{3}", Request.Url.Host + 
            (Request.Url.Port > 80 ? ":" + Request.Url.Port.ToString() : ""), 
            _Root, path, d.Name) 
          }); 
        }
        // files
        foreach (FileInfo f in DI.GetFiles())
        {
          files.Add(new
          {
            name = f.Name,
            size = f.Length,
            type = 1,// type = 1 - is file
            url = String.Format("http://{0}/{1}{2}{3}", Request.Url.Host + 
            (Request.Url.Port > 80 ? ":" + Request.Url.Port.ToString() : ""), 
            _Root, path, f.Name)
          }); 
        }
        // check top-level directory
        bool allowUp = !String.IsNullOrEmpty(path.Trim("/".ToCharArray()));
        // create JSON
        result = GetJsonString(new { stat = "ok", allowUp = allowUp, data = files });
        #endregion
      }
    }
    catch (Exception ex)
    {
      // error
      result = GetError(ex.Message);
    }

    // result
    return result.ToString();
  }

  /// <span class="code-SummaryComment"><summary>
</span>  /// The helper function returning error in the JSON
  /// <span class="code-SummaryComment"></summary>
</span>  /// <span class="code-SummaryComment"><param name="msg">Error message</param>
</span>  private StringBuilder GetError(string msg)
  {
    return GetJsonString(new { stat = "err", msg = msg });
  }

  /// <span class="code-SummaryComment"><summary>
</span>  /// The helper function for converting object to JSON
  /// <span class="code-SummaryComment"></summary>
</span>  /// <span class="code-SummaryComment"><param name="source">Object for converting JSON</param>
</span>  private StringBuilder GetJsonString(object source)
  {
    StringBuilder result = new StringBuilder();
    JavaScriptSerializer myJSON = new JavaScriptSerializer();
    myJSON.Serialize(source, result);
    return result;
  }
}

The Gateway class is easy to use ASP. NET WebForms. For example, in the ASP .NET Handler (Gateway.ashx).

public class Gateway : IHttpHandler
{
  public void ProcessRequest(HttpContext context)
  {
    Nemiro.FileManager.Common.Gateway myGateway = 
		new Nemiro.FileManager.Common.Gateway();
    context.Response.ContentType = "application/json";
    context.Response.Write(myGateway.GetResult());
  }

  public bool IsReusable
  {
    get
    {
      return false;
    }
  }
}

And also in the ASP .NET MVC. For example, to the Gateway Action in HomeController.

public class HomeController : Controller
{
  [HttpPost]
  public ActionResult Gateway()
  {
    Nemiro.FileManager.Common.Gateway myGateway = 
		new Nemiro.FileManager.Common.Gateway();
    return new ContentResult() { Content = myGateway.GetResult(), 
	ContentType = "application/json", ContentEncoding = System.Text.Encoding.UTF8 };
  }
}

Silveright (client)

WebHelper Class

The WebHelper class implements the ability to send asynchronous HTTP requests.

For request parameters, I created two additional classes.

First - the QueryItem class for parameter data. The QueryItem class can contain text data and files. Second - the QueryItemCollection collections of QueryItem.

The WebHelper class has a one public method - Execute. The method takes a reference to a callback function.

For callback function, I created delegate.

public delegate void WebCallback(string stat, string msg, bool allowUp, 
	JsonValue data, object tag);

As you can see, to the callback function will be transferred server response from JSON. It is special for File Manager, but you can change delegate and callback function, it is easy.

public class WebHelper
{
  /// <span class="code-SummaryComment"><summary>
</span>  /// The delegate  for callback function
  /// <span class="code-SummaryComment"></summary>
</span>  /// <span class="code-SummaryComment"><param name="stat">Server response code (ok, err)</param>
</span>  /// <span class="code-SummaryComment"><param name="msg">Error message  (only for stat = err)</param>
</span>  /// <span class="code-SummaryComment"><param name="allowUp">Has top-level directory</param>
</span>  /// <span class="code-SummaryComment"><param name="data">Array of file list</param>
</span>  public delegate void WebCallback
	(string stat, string msg, bool allowUp, JsonValue data, object tag);
  // public delegate void WebCallback(HttpWebResponse resp);

  private string _Method = "POST";
  private QueryItemCollection _Queries = new QueryItemCollection();
  private string _Url = String.Empty;

  private string _Boundary = String.Empty;
  private WebCallback _Callback = null;

  /// <span class="code-SummaryComment"><summary>
</span>  /// GET or POST
  /// <span class="code-SummaryComment"></summary>
</span>  public string Method
  {
    get
    {
      return _Method;
    }
    set
    {
      _Method = value;
      if (String.IsNullOrEmpty(_Method) || _Method.ToUpper() != "GET" || 
      	_Method.ToUpper() != "POST") _Method = "POST";
    }
  }

  /// <span class="code-SummaryComment"><summary>
</span>  /// Parameters of Request
  /// <span class="code-SummaryComment"></summary>
</span>  public QueryItemCollection Queries
  {
    get
    {
      return _Queries;
    }
    set
    {
      _Queries = value;
    }
  }

  /// <span class="code-SummaryComment"><summary>
</span>  /// Url for sending request
  /// <span class="code-SummaryComment"></summary>
</span>  public string Url
  {
    get
    {
      return _Url;
    }
    set
    {
      _Url = value;
    }
  }

  /// <span class="code-SummaryComment"><summary>
</span>  /// Additional custom property
  /// <span class="code-SummaryComment"></summary>
</span>  public object Tag { get; set; }

  public WebHelper(string url) : this (url, "POST") { }
  public WebHelper(string url, string method)
  {
    this.Url = url;
    this.Method = method;
  }

  /// <span class="code-SummaryComment"><summary>
</span>  /// Execute the Request
  /// <span class="code-SummaryComment"></summary>
</span>  /// <span class="code-SummaryComment"><param name="callback">The callback function</param>
</span>  public void Execute(WebCallback callback)
  {
    if (String.IsNullOrEmpty(_Url))
    {
      // url is empty
      return;
    }

    _Callback = callback;
    string url = _Url;

    #region add parameters to url for GET requests
    if (_Method == "GET")
    {
      string qs = _Queries.GetQueryString();
      if (url.EndsWith("?"))
      {
        url += "&" + qs;
      }
      else
      {
        url += "?" + qs;
      }
    }
    #endregion

    HttpWebRequest myReq = (HttpWebRequest)HttpWebRequest.Create(_Url);
    myReq.Method = _Method;

    #region Content-Type for POST requests
    if (_Method == "POST")
    {
      if (_Queries.HasFiles())
      {
        // has files, this is multipart/form-data content type
        _Boundary = "----------" + DateTime.Now.Ticks.ToString("x"); // random boundary
        myReq.ContentType = "multipart/form-data; boundary=" + _Boundary;
      }
      else
      {
        // has not files, this is application/x-www-form-urlencoded content type
        myReq.ContentType = "application/x-www-form-urlencoded";
      }
    }
    #endregion

    // start requests
    myReq.BeginGetRequestStream(Execute_BeginGetRequestStream, myReq);
  }
  private void Execute_BeginGetRequestStream(IAsyncResult result)
  {
    HttpWebRequest r = result.AsyncState as HttpWebRequest; // get request

    #region write parameters to request (only for POST)
    if (_Queries.Count > 0 && _Method == "POST")
    {
      Stream myStream = r.EndGetRequestStream(result);

      // no the boundary
      if (String.IsNullOrEmpty(_Boundary))
      {
        // write parameters as string
        byte[] buffer = Encoding.UTF8.GetBytes(_Queries.GetQueryString());
        myStream.Write(buffer, 0, buffer.Length);

      }
      // has the boundary
      else
      {
        // write parameters with headers
        byte[] buffer = null;
        foreach (QueryItem itm in _Queries)
        {
          if (!itm.IsFile)
          {
            // the text parameter
            string q = String.Format("\r\n--{0}\r\nContent-Disposition: 
            form-data; name=\"{1}\";\r\n\r\n{2}", 
		_Boundary, itm.Name, itm.ValueAsString());
            buffer = Encoding.UTF8.GetBytes(q);
            myStream.Write(buffer, 0, buffer.Length);
          }
          else
          {
            // the file
            string q = String.Format("\r\n--{0}\r\nContent-Disposition: 
            form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n", 
            _Boundary, itm.Name, itm.FileName, itm.GetContentType());
            buffer = Encoding.UTF8.GetBytes(q);
            // file headers
            myStream.Write(buffer, 0, buffer.Length);
            // file body
            buffer = new byte[4096]; // 4 Kb
            int bytesRead = 0; int totalSize = 0;
            while ((bytesRead = ((Stream)itm.Value).Read
		(buffer, 0, buffer.Length)) != 0) // read file data
            {
              myStream.Write(buffer, 0, buffer.Length); // write file to request
              totalSize += bytesRead;
            }
          }
        }

        // close the boundary
        buffer = Encoding.UTF8.GetBytes(String.Format("\r\n--{0}--\r\n", _Boundary));
        myStream.Write(buffer, 0, buffer.Length);

      }

      myStream.Close();
    }
    #endregion

    // get response
    r.BeginGetResponse(Execute_Complete, r);
  }
  private void Execute_Complete(IAsyncResult result)
  {
    HttpWebRequest myReq = (HttpWebRequest)result.AsyncState;
    HttpWebResponse myResp = (HttpWebResponse)myReq.EndGetResponse(result);

    string stat = "", msg = "";
    bool allowUp = false;
    JsonValue data = null;

    if (myResp.StatusCode == HttpStatusCode.OK) //HTTP 200 - OK
    {
      // read response
      StreamReader reader = new StreamReader(myResp.GetResponseStream(), Encoding.UTF8);
      string page = reader.ReadToEnd();
      // parse JSON
      JsonValue json = System.Json.JsonObject.Parse(page);
      if (json.ContainsKey("stat")) stat = json["stat"];
      if (json.ContainsKey("msg")) msg = json["msg"];
      if (json.ContainsKey("allowUp")) allowUp = json["allowUp"];
      if (json.ContainsKey("data")) data = json["data"];
    }
    else
    {
      stat = "err";
      msg = String.Format("Server error {0}", myResp.StatusCode);
    }

    // callback
    if (_Callback != null)
    {
      _Callback(stat, msg, allowUp, data, this.Tag);
      // _Callback(myResp);
    }
  }

  #region additional classes
  /// <span class="code-SummaryComment"><summary>
</span>  /// Collection parameters of request
  /// <span class="code-SummaryComment"></summary>
</span>  public class QueryItemCollection : List<QueryItem>
  {

    /// <span class="code-SummaryComment"><summary>
</span>    /// Add text parameter
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><param name="name">Parameter name</param>
</span>    /// <span class="code-SummaryComment"><param name="value">Parameter value</param>
</span>    public void Add(string name, string value)
    {
      this.Add(new QueryItem(name, value));
    }

    /// <span class="code-SummaryComment"><summary>
</span>    /// Add file
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><param name="name">Parameter name</param>
</span>    /// <span class="code-SummaryComment"><param name="fileName">File name</param>
</span>    /// <span class="code-SummaryComment"><param name="stream">File stream</param>
</span>    public void Add(string name, string fileName, Stream stream)
    {
      this.Add(new QueryItem(name, fileName, stream));
    }

    /// <span class="code-SummaryComment"><summary>
</span>    /// The function return parameters as string (par1=val1&par2=val2&par3=val3 etc.)
    /// <span class="code-SummaryComment"></summary>
</span>    public string GetQueryString()
    {
      string qs = "";
      foreach (QueryItem itm in this)
      {
        if (!String.IsNullOrEmpty(qs)) qs += "&";
        qs += String.Format("{0}={1}", itm.Name, itm.ValueForUrl());
      }
      return qs;
    }

    /// <span class="code-SummaryComment"><summary>
</span>    /// The function search files. If has files, function returned "true".
    /// <span class="code-SummaryComment"></summary>
</span>    public bool HasFiles()
    {
      foreach (QueryItem itm in this)
      {
        if (itm.IsFile) return true;
      }
      return false;
    }
  }

  /// <span class="code-SummaryComment"><summary>
</span>  /// Parameter of request
  /// <span class="code-SummaryComment"></summary>
</span>  public class QueryItem
  {

    public string Name { get; set; }
    public object Value{get;set;}
    public string FileName { get; set; }

    /// <span class="code-SummaryComment"><summary>
</span>    /// Is file or is not file
    /// <span class="code-SummaryComment"></summary>
</span>    public bool IsFile
    {
      get
      {
        return this.Value != null && this.Value.GetType() == typeof(FileStream);
      }
    }

    public QueryItem(string name, string value)
    {
      this.Name = name;
      this.Value = value;
    }

    public QueryItem(string name, string fileName, Stream stream)
    {
      this.Name = name;
      this.FileName = fileName;
      this.Value = stream;
    }

    /// <span class="code-SummaryComment"><summary>
</span>    /// UrlEncode value
    /// <span class="code-SummaryComment"></summary>
</span>    public string ValueForUrl()
    {
      return HttpUtility.UrlEncode(this.Value.ToString());
    }
    /// <span class="code-SummaryComment"><summary>
</span>    /// Value as string
    /// <span class="code-SummaryComment"></summary>
</span>    public string ValueAsString()
    {
      return this.Value.ToString();
    }

    /// <span class="code-SummaryComment"><summary>
</span>    /// Content-Type by file extension
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><returns></returns>
</span>    public string GetContentType()
    { // cut from article (please see the project source files)
      return "application/data";
    }
  }
  #endregion
}

FileList Control

The FileList control inherited from ListBox. Each item will also be custom.

FileItem

The FileItem class inherited from StackPanel. The Item will contain an icon, name, file size and 3 buttons for open, rename and delete item. But the class cannot independently send requests to server. This is only possible via FileList (Parent).

public class FileItem : StackPanel
{
  /// <span class="code-SummaryComment"><summary>
</span>  /// Item type: -1 - top-level directory, 0 - directory, 1 - file
  /// <span class="code-SummaryComment"></summary>
</span>  public int ItemType { get; set; }
  /// <span class="code-SummaryComment"><summary>
</span>  /// Directory/File name
  /// <span class="code-SummaryComment"></summary>
</span>  public string FileName { get; set; }
  /// <span class="code-SummaryComment"><summary>
</span>  /// File size (Kb)
  /// <span class="code-SummaryComment"></summary>
</span>  public double FileSize { get; set; }
  /// <span class="code-SummaryComment"><summary>
</span>  /// File url
  /// <span class="code-SummaryComment"></summary>
</span>  public string FileUrl { get; set; }
  /// <span class="code-SummaryComment"><summary>
</span>  /// True - item is in edit mode. 
  /// False - item is not in edit mode.
  /// <span class="code-SummaryComment"></summary>
</span>  public bool IsEdit { get; set; }
  /// <span class="code-SummaryComment"><summary>
</span>  /// Can edit the Item
  /// <span class="code-SummaryComment"></summary>
</span>  public bool CanEdit { get; set; }

  private string _NewName = "";
  /// <span class="code-SummaryComment"><summary>
</span>  /// New Directory/File name
  /// <span class="code-SummaryComment"></summary>
</span>  public string NewName
  {
    get
    {
      return _NewName;
    }
  }

  private int _ItemIndex = 0;

  public FileItem(int type, string name, string url, double size)
  {
    this.ItemType = type;
    this.FileName = name;
    this.FileUrl = url;
    this.FileSize = size;
    this.CanEdit = type != -1; // top-level directory cannot be editable

    this.Orientation = Orientation.Horizontal;

    // item icon
    Image myImg = new Image() { Width = 16, Height = 16 };
    if (type == -1)
    {
      // top-level directory
      myImg.Source = new System.Windows.Media.Imaging.BitmapImage
		(new Uri("Images/folder2.png", UriKind.Relative));
    }
    else if (type == 0)
    {
      // directory
      myImg.Source = new System.Windows.Media.Imaging.BitmapImage
		(new Uri("Images/folder.png", UriKind.Relative));
    }
    else
    {
      // file
      // set icon by extension
      string fileExtension = System.IO.Path.GetExtension(name).ToLower();
      string[] fileType = { ".exe", ".bat", ".cmd", ".asp", ".aspx", ".html", 
      ".htm", ".cs", ".txt", ".doc", ".docx", ".php", ".gif", ".png", ".jpg", 
      ".jpeg", ".bmp", ".js", ".xls", "xlsx", ".zip" };
      string[] fileIcon = { "exe.png", "cmd.png", "cmd.png", "aspx.png", "aspx.png", 
      "html.png", "html.png", "csharp.png", "txt.png", "doc.png", "doc.png", "php.png", 
      "image.png", "image.png", "image.png", "image.png", "bmp.png", 
      "script.png", "xls.png", "xls.png", "zip.png" };
      int idx = Array.IndexOf(fileType, fileExtension);
      if (idx != -1)
      {
        myImg.Source = new System.Windows.Media.Imaging.BitmapImage
        (new Uri("Images/" + fileIcon[idx], UriKind.Relative));
      }
      else
      {
        // default file icon
        myImg.Source = new System.Windows.Media.Imaging.BitmapImage
        (new Uri("Images/unknown.png", UriKind.Relative));
      }
    }
    myImg.Margin = new Thickness(2, 0, 0, 0);
    this.Children.Add(myImg);

    // file/directory name
    this.Children.Add(new TextBlock() 
	{ Text = name, Margin = new Thickness(2, 0, 0, 0) });

    // control buttons
    // open file or go into directory
    Image myImg2 = new Image() { Width = 9, Height = 9, Cursor = Cursors.Hand };
    myImg2.Margin = new Thickness(4, 0, 0, 0);
    myImg2.Source = new System.Windows.Media.Imaging.BitmapImage
    (new Uri("Images/open.png", UriKind.Relative));
    myImg2.MouseLeftButtonUp += (sender, e) =>
    {
      Open();
    };
    this.Children.Add(myImg2);

    // is not top-level directory
    if (type != -1)
    {
      // rename directory/file 
      Image myImg4 = new Image() { Width = 9, Height = 9, Cursor = Cursors.Hand };
      myImg4.Margin = new Thickness(4, 0, 0, 0);
      myImg4.Source = new System.Windows.Media.Imaging.BitmapImage
      (new Uri("Images/edit.png", UriKind.Relative));
      myImg4.MouseLeftButtonUp += (sender, e) =>
      {
        EditStart();
      };
      this.Children.Add(myImg4);

      // delete directory/file 
      Image myImg3 = new Image() { Width = 9, Height = 9, Cursor = Cursors.Hand };
      myImg3.Margin = new Thickness(4, 0, 0, 0);
      myImg3.Source = new System.Windows.Media.Imaging.BitmapImage
      (new Uri("Images/del.png", UriKind.Relative));
      myImg3.MouseLeftButtonUp += (sender, e) =>
      {
        Delete();
      };
      this.Children.Add(myImg3);
    }

    // file size
    if (type == 1) // only for files
    {
      this.Children.Add(new TextBlock() { Text = String.Format
      ("{0:##,###,##0.00} Kb", size), HorizontalAlignment = 
      System.Windows.HorizontalAlignment.Right, Margin = new Thickness(8, 0, 0, 0), 
      FontSize = 9, Foreground = 
	new SolidColorBrush(Color.FromArgb(255, 128, 128, 128)) });
    }

    this.MouseLeftButtonUp += new MouseButtonEventHandler(FileItem_MouseLeftButtonUp);
  }

  private DateTime _lastClick = DateTime.Now;
  private bool _firstClickDone = false;
  private void FileItem_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
  {
    DateTime clickTime = DateTime.Now;
    TimeSpan span = clickTime - _lastClick;
    if (span.TotalMilliseconds > 350 || !_firstClickDone)//350 ms
    {
      // first click
      _firstClickDone = true;
      _lastClick = clickTime;
    }
    else
    {
      // second click
      _firstClickDone = false;
      // open file or go into directory
      Open();
    }
  }

  /// <span class="code-SummaryComment"><summary>
</span>  /// Start editing (change TextBlock to TextBox and set IsEdit = true)
  /// <span class="code-SummaryComment"></summary>
</span>  public void EditStart()
  {
    if (this.IsEdit) return;
    // remove TextBlock
    this.Children.RemoveAt(1);
    // add TextBox
    this.Children.Insert(1, new TextBox() 
    { Text = this.FileName, Margin = new Thickness(2, 0, 0, 0) });
    // set TextBox LostFocus handler
    ((TextBox)this.Children[1]).LostFocus += 
	new RoutedEventHandler(EditTextBox_LostFocus);
    // select all text for directories
    if (this.ItemType == 0)
    {
      ((TextBox)this.Children[1]).SelectAll();
    }
    else
    {
      // select only file name for files (excluding file extension)
      ((TextBox)this.Children[1]).SelectionStart = 0;
      ((TextBox)this.Children[1]).SelectionLength = this.FileName.LastIndexOf(".");
    }
    // remember item index
    _ItemIndex = ((FileList)this.Parent).SelectedIndex;
    // set focus to TextBox
    ((TextBox)this.Children[1]).Focus();
    this.IsEdit = true;
  }
  /// <span class="code-SummaryComment"><summary>
</span>  /// TextBox LostFocus handler
  /// <span class="code-SummaryComment"></summary>
</span>  private void EditTextBox_LostFocus(object sender, RoutedEventArgs e)
  {
    EditComplete();
  }
  /// <span class="code-SummaryComment"><summary>
</span>  /// Cancel editing (change TextBox to TextBlock and set IsEdit = false)
  /// <span class="code-SummaryComment"></summary>
</span>  public void EditCancel()
  {
    // remove TextBox
    this.Children.RemoveAt(1);
    // add TextBlock
    this.Children.Insert(1, new TextBlock() 
    { Text = this.FileName, Margin = new Thickness(2, 0, 0, 0) });
    this.IsEdit = false;
    ((FileList)this.Parent).Focus();
  }
  /// <span class="code-SummaryComment"><summary>
</span>  /// Finish editing and send request to server for rename item
  /// <span class="code-SummaryComment"></summary>
</span>  public void EditComplete()
  {
    // remove TextBox LostFocus handler
    ((TextBox)this.Children[1]).LostFocus -= EditTextBox_LostFocus;
    // get new name
    _NewName = ((TextBox)this.Children[1]).Text;
    // send request for rename item
    ((FileList)this.Parent).SetNewName(this);
  }

  /// <span class="code-SummaryComment"><summary>
</span>  /// Open file or go into the directory
  /// <span class="code-SummaryComment"></summary>
</span>  public void Open()
  {
    if (this.ItemType == 1)
    {
      // open file in new window
      HtmlPage.PopupWindow(new Uri(this.FileUrl), "_blank", null);
    }
    else if (this.ItemType == 0)
    {
      // this is directory, 
      // append current item to patch
      if (!((FileList)this.Parent).Path.EndsWith("/")) 
		((FileList)this.Parent).Path += "/";
      ((FileList)this.Parent).Path += this.FileName;
      // update file list
      ((FileList)this.Parent).UpdateFileList();
    }
    else if (this.ItemType == -1)
    {
      // this is top-level directory, 
      // remove last item from path
      string[] arr = ((FileList)this.Parent).Path .Split("/".ToCharArray());
      Array.Resize(ref arr, arr.Length - 1);
      ((FileList)this.Parent).Path  = String.Join("/", arr);
      // update file list
      ((FileList)this.Parent).UpdateFileList();
    }
  }

  /// <span class="code-SummaryComment"><summary>
</span>  /// Delete item
  /// <span class="code-SummaryComment"></summary>
</span>  public void Delete()
  {
    if (this.ItemType == 0)
    {
      if (MessageBox.Show(String.Format("Are you want delete the directory 
      \"{0}\"?", this.FileName), "Delete", 
	MessageBoxButton.OKCancel) == MessageBoxResult.OK)
      {
        ((FileList)this.Parent).DeleteItem(this);
      }
    }
    else if (this.ItemType == 1)
    {
      if (MessageBox.Show(String.Format("Are you want delete the file 
      \"{0}\"?", this.FileName), "Delete", 
      MessageBoxButton.OKCancel) == MessageBoxResult.OK)
      {
        ((FileList)this.Parent).DeleteItem(this);
      }
    }
  }
}

FileList

The FileList contains a helper method for showing errors via standard MessageBox. Because the requests are executed in separate threads, MessageBox can be called only from the main thread via BeginInvoke.

private void ShowError(string msg)
{
  this.Dispatcher.BeginInvoke(() =>
  {
    MessageBox.Show(msg, "Error", MessageBoxButton.OK);
  });
}

To implement the ProgressBar, the class contain two events: Process and Complete.

public event EventHandler Process;
public event EventHandler Complete;

ProgressBar will not be to the FileList, is it external (to page). For progress, I created child windows.

private string _Url = "http://localhost:58646/Gateway.ashx"; // gateway url for requests
private PleaseWait myPleaseWait = null;

public MainPage()
{
  InitializeComponent();

  fileList1.Url = _Url; //set url

  // handlers for progress
  fileList1.Process += new EventHandler(fileList1_Process);
  fileList1.Complete += new EventHandler(fileList1_Complete);
}

private void fileList1_Process(object sender, EventArgs e)
{
  this.Dispatcher.BeginInvoke(() =>
  {
    if (myPleaseWait != null && 
    myPleaseWait.Visibility == System.Windows.Visibility.Visible) return;
    // show porgress
    myPleaseWait = new PleaseWait();
    myPleaseWait.Show();
  });
}

private void fileList1_Complete(object sender, EventArgs e)
{
  this.Dispatcher.BeginInvoke(() =>
  {
    //close progress
    if (myPleaseWait != null)
    {
      myPleaseWait.Close();
      myPleaseWait = null;
    }
    // set new path from fileList
    tbPath.Text = fileList1.Path;
  });
}

For upload files, I created helper class UploadItem because sending is done in two stages:

  1. check
  2. upload
public class UploadItem
{
  /// <span class="code-SummaryComment"><summary>
</span>  /// The event occurs after the request is sent
  /// <span class="code-SummaryComment"></summary>
</span>  public event EventHandler Complete;

  /// <span class="code-SummaryComment"><summary>
</span>  /// State code list
  /// <span class="code-SummaryComment"></summary>
</span>  public enum StateList
  {
    /// <span class="code-SummaryComment"><summary>
</span>    /// File sent successfully
    /// <span class="code-SummaryComment"></summary>
</span>    OK,
    /// <span class="code-SummaryComment"><summary>
</span>    /// Error
    /// <span class="code-SummaryComment"></summary>
</span>    Error,
    /// <span class="code-SummaryComment"><summary>
</span>    /// File is waiting
    /// <span class="code-SummaryComment"></summary>
</span>    Wait
  }

  private StateList _State = StateList.Wait;
  private string _Message = String.Empty;
  private int _Index = 0;
  private string _FileName = String.Empty;
  private Stream _FileStream = null;
  private string _Path = String.Empty;
  private string _Url = String.Empty;

  /// <span class="code-SummaryComment"><summary>
</span>  /// Upload state
  /// <span class="code-SummaryComment"></summary>
</span>  public StateList State
  {
    get { return _State; }
  }

  /// <span class="code-SummaryComment"><summary>
</span>  /// Error message
  /// <span class="code-SummaryComment"></summary>
</span>  public string Message
  {
    get { return _Message; }
  }

  /// <span class="code-SummaryComment"><summary>
</span>  /// File name
  /// <span class="code-SummaryComment"></summary>
</span>  public string FileName
  {
    get { return _FileName; }
  }

  /// <span class="code-SummaryComment"><summary>
</span>  /// File index
  /// <span class="code-SummaryComment"></summary>
</span>  public int Index
  {
    get { return _Index; }
  }

  /// <span class="code-SummaryComment"><param name="f">File</param>
</span>  /// <span class="code-SummaryComment"><param name="idx">File index</param>
</span>  /// <span class="code-SummaryComment"><param name="url">Url for uploading</param>
</span>  /// <span class="code-SummaryComment"><param name="path">Server path</param>
</span>  public UploadItem(int idx, FileInfo f, string url, string path)
  {
    _Index = idx;
      
    _Path = path;
    _Url = url;

    _FileName = f.Name; // set file name
    _FileStream = f.OpenRead(); // open file stream
  }

  public void Run()
  {
    try
    {
      // send request for check server
      WebHelper w = new WebHelper(_Url);
      w.Queries.Add("cmd", "check");
      w.Queries.Add("path", _Path);
      w.Queries.Add("name", _FileName);
      w.Execute(CheckNameResult);
    }
    catch (Exception ex)
    {
      _State = StateList.Error;
      _Message = ex.Message;
      if(Complete != null) Complete(this, null);
    }
  }
  private void CheckNameResult(string stat, string msg, 
		bool allowUp, JsonValue data, object tag)
  {
    try
    {
      if (stat == "ok")
      {
        // send file
        WebHelper w = new WebHelper(_Url);
        w.Queries.Add("cmd", "upload");
        w.Queries.Add("path", _Path);
        w.Queries.Add("file1", _FileName, _FileStream);//add file to request
        w.Execute(UploadResult);
      }
      else
      {
        // error
        _State = StateList.Error;
        _Message = msg;
        if(Complete != null) Complete(this, null);
      }
    }
    catch (Exception ex)
    {
      _State = StateList.Error;
      _Message = ex.Message;
      if(Complete != null) Complete(this, null);
    }
  }
  private void UploadResult(string stat, string msg, bool allowUp, 
		JsonValue data, object tag)
  {
    if (stat == "ok")
    {
      _State = StateList.OK;
    }
    else
    {
      // error
      _State = StateList.Error;
      _Message = msg;
    }
    if(Complete != null) Complete(this, null);
  }
}

The FileList control has a UploadList collection.

private List<UploadItem> _UploadFiles = null;

And method for adding UploadItem to collection.

public void AddUploadItem(FileInfo f)
{
  if (_UploadFiles == null) _UploadFiles = new List<uploaditem />();
  UploadItem itm = new UploadItem(_UploadFiles.Count, f, this.Url, this.Path);
  itm.Complete += new EventHandler(UploadItem_Complete);
  _UploadFiles.Add(itm);
}

The FileList can take files via Drag and Drop.

this.Drop += new DragEventHandler(FileList_Drop);
private void FileList_Drop(object sender, DragEventArgs e)
{
  // add selected files to upload list
  FileInfo[] files = e.Data.GetData(DataFormats.FileDrop) as FileInfo[];
  foreach (FileInfo f in files)
  {
    this.AddUploadItem(f); 
  }

  // upload files
  this.Upload();
}

Uploading files starting on the Upload method each from _UploadList.

public void Upload()
{
  if (_UploadFiles == null || _UploadFiles.Count <= 0) return; // upload list is empty
      
  _UploadErrorMessages = new StringBuilder();

  if (Process!=null) Process(this, null);;

  foreach (UploadItem itm in _UploadFiles)
  {
    itm.Run();//start upload file
  }
}

After sending the file to the server, it is removed from _UploadList on the UploadItem_Complete handler. When the files over, FileList update the list of files from server.

private void UploadItem_Complete(object sender, EventArgs e)
{
  this.Dispatcher.BeginInvoke(() =>
  {
    UploadItem itm = sender as UploadItem;
    if (itm.State == UploadItem.StateList.Error)
    {
      _UploadErrorMessages.AppendLine(itm.Message);
    }
    // remove file from upload list
    _UploadFiles.Remove(itm);
    if (_UploadFiles.Count == 0)
    {
      // upload list is empty
      // start Complete
      if (Complete != null) Complete(this, null);
      // has error?
      if (_UploadErrorMessages.Length <= 0)
      {
        // no error, update file list
        UpdateFileList();
      }
      else
      {
        // show error message
        ShowError(_UploadErrorMessages.ToString());
      }
    }
  });
}

The entire code of the FileList class.

public class FileList : ListBox
{

  /// <span class="code-SummaryComment"><summary>
</span>  /// The event occurs before the request is sent
  /// <span class="code-SummaryComment"></summary>
</span>  public event EventHandler Process;
  /// <span class="code-SummaryComment"><summary>
</span>  /// The event occurs after the request is sent
  /// <span class="code-SummaryComment"></summary>
</span>  public event EventHandler Complete;

  private string _Url = "";
  private string _Path = "/";
  private List<UploadItem> _UploadFiles = null; // the file list to upload 
  private StringBuilder _UploadErrorMessages = null; // upload error messages

  /// <span class="code-SummaryComment"><summary>
</span>  /// The path of the directory on the server
  /// <span class="code-SummaryComment"></summary>
</span>  public string Path
  {
    get
    {
      return _Path;
    }
    set
    {
      _Path = value;
      if (String.IsNullOrEmpty(_Path)) _Path = "/";
    }
  }

  /// <span class="code-SummaryComment"><summary>
</span>  /// The file list to upload 
  /// <span class="code-SummaryComment"></summary>
</span>  public List<UploadItem> UploadFiles
  {
    get
    {
      return _UploadFiles;
    }
  }

  /// <span class="code-SummaryComment"><summary>
</span>  /// Gateway url
  /// <span class="code-SummaryComment"></summary>
</span>  public string Url
  {
    get
    {
      return _Url;
    }
    set
    {
      _Url = value;
      if (!System.ComponentModel.DesignerProperties.IsInDesignTool)// is not 
							// Visual Studio designer
      { //update file list
        UpdateFileList();
      }
    }
  }

  public FileList()
  {
    ImageBrush ib = new ImageBrush();
    ib.ImageSource = new System.Windows.Media.Imaging.BitmapImage
    (new Uri("Images/2.png", UriKind.Relative));
    ib.Stretch = Stretch.Fill;
    this.Background = ib;
    this.AllowDrop = true;
    this.KeyUp += new KeyEventHandler(FileList_KeyUp); // add KeyUp handler
    this.Drop += new DragEventHandler(FileList_Drop); // add Drop handler
  }

  /// <span class="code-SummaryComment"><summary>
</span>  /// FileList KeyUp handler
  /// <span class="code-SummaryComment"></summary>
</span>  private void FileList_KeyUp(object sender, KeyEventArgs e)
  {
    if (((FileList)sender).SelectedItem == null) return;
    FileItem itm = ((FileList)sender).SelectedItem as FileItem;
    if (e.Key == Key.Enter && !itm.IsEdit)
    { // open file or go into the directory
      itm.Open();
    }
    else if (e.Key == Key.Enter && itm.IsEdit)
    { // finish editing
      itm.EditComplete();
    }
    else if (e.Key == Key.F2 && itm.CanEdit && !itm.IsEdit)
    { // start editing
      itm.EditStart();
    }
    else if (e.Key == Key.Escape && itm.IsEdit)
    { // cancel editing
      itm.EditCancel();
    }
    else if (e.Key == Key.Delete && !itm.IsEdit)
    { // delete file or directory
      itm.Delete();
    }
    else if (e.Key == Key.F5)
    { // update file list
      UpdateFileList();
    }
  }

  #region update file list
  /// <span class="code-SummaryComment"><summary>
</span>  /// Send request to the server for a list of files
  /// <span class="code-SummaryComment"></summary>
</span>  public void UpdateFileList()
  {
    if (Process!=null) Process(this, null);; // start Process

    // send request
    WebHelper w = new WebHelper(this.Url);
    w.Queries.Add("cmd", "get");
    w.Queries.Add("path", _Path);
    w.Execute(UpdateFileListResult); // the server response 
    		//we can find in the UpdateFileListResult method
  }
  private void UpdateFileListResult
  (string stat, string msg, bool allowUp, JsonValue data, object tag)
  {
    if (stat == "ok")
    {
      // crear FileList items
      this.Dispatcher.BeginInvoke(() =>
      {
        this.Items.Clear();
      });

      // add top-level directory
      if (allowUp)
      {
        AddItem(-1, "...", "", 0);
      }

      // add files and directories
      if (data != null && data.Count > 0)
      {
        foreach (JsonValue itm in data)
        {
          AddItem(itm["type"], itm["name"], itm["url"], itm["size"]);
        }
      }

      // set focus to the first item
      this.Dispatcher.BeginInvoke(() =>
      {
        this.SelectedIndex = -1;
        this.Focus();
        if (this.Items.Count > 0) this.SelectedIndex = 0;
      });
    }
    else
    {
      // show error message
      ShowError("Error. " + msg);
    }

    if (Complete != null) Complete(this, null); // start Complete
  }
    
  /// <span class="code-SummaryComment"><summary>
</span>  /// The method adds an item to the list
  /// <span class="code-SummaryComment"></summary>
</span>  /// <span class="code-SummaryComment"><param name="type">Item type: -1 - top-level directory, 
</span>  /// 0 - directory, 1 - file<span class="code-SummaryComment"></param>
</span>  /// <span class="code-SummaryComment"><param name="name">Name</param>
</span>  /// <span class="code-SummaryComment"><param name="size">File size (kb)</param>
</span>  private void AddItem(int type, string name, string url, double size)
  {
    this.Dispatcher.BeginInvoke(() =>
    {
      FileItem itm = new FileItem(type, name, url, size);
      this.Items.Add(itm);
    });
  }
  #endregion
  #region rename file or directory
  /// <span class="code-SummaryComment"><summary>
</span>  /// Send request to the server for rename item
  /// <span class="code-SummaryComment"></summary>
</span>  public void SetNewName(FileItem itm)
  {
    if (itm == null || !itm.IsEdit)
    {
      MessageBox.Show("The item can not be changed!", "Error", MessageBoxButton.OK);
      return;
    }

    if (Process!=null) Process(this, null);

    // send request
    WebHelper w = new WebHelper(this.Url);
    w.Queries.Add("cmd", "rename");
    w.Queries.Add("path", _Path);
    w.Queries.Add("oldName", itm.FileName);
    w.Queries.Add("newName", itm.NewName);
    w.Tag = itm; //pass the item to instance of the WebHelper 
    w.Execute(SetNewNameResult);
  }
  private void SetNewNameResult(string stat, string msg, 
		bool allowUp, JsonValue data, object tag)
  {
    if (stat == "ok")
    {
      // rename item in the FileList
      this.Dispatcher.BeginInvoke(() =>
      {
        FileItem itm = tag as FileItem;
        itm.FileName = itm.NewName; 
        itm.FileUrl = itm.FileUrl.Substring
			(0, itm.FileUrl.LastIndexOf("/") + 1) + itm.FileName;
        itm.EditCancel(); // change TextBox to TextBlock
      });
    }
    else
    {
      ShowError("Error. " + msg);
    }

    if (Complete != null) Complete(this, null);
  }
  #endregion
  #region delete file or directory
  /// <span class="code-SummaryComment"><summary>
</span>  /// Send request to the server for delete item
  /// <span class="code-SummaryComment"></summary>
</span>  public void DeleteItem(FileItem itm)
  {
    if (Process!=null) Process(this, null);

    // send request
    WebHelper w = new WebHelper(this.Url);
    w.Queries.Add("cmd", "delete"); 
    w.Queries.Add("path", _Path);
    w.Queries.Add("name", itm.FileName);
    w.Tag = itm;  //pass the item to instance of the WebHelper 
    w.Execute(DeleteItemResult);
  }
  private void DeleteItemResult
  (string stat, string msg, bool allowUp, JsonValue data, object tag)
  {
    if (stat == "ok")
    {
      // delete item from the FileList
      this.Dispatcher.BeginInvoke(() =>
      {
        FileItem itm = tag as FileItem;
        this.Items.Remove(itm);
      });

    }
    else
    {
      ShowError("Error. " + msg);
    }

    if (Complete != null) Complete(this, null);
  }
  #endregion
  #region create new directory
  /// <span class="code-SummaryComment"><summary>
</span>  /// Send request to the server for create a new directory
  /// <span class="code-SummaryComment"></summary>
</span>  /// <span class="code-SummaryComment"><param name="name">Directory name</param>
</span>  public void CreateDirectory(string name)
  {
    if (Process!=null) Process(this, null);

    // send request
    WebHelper w = new WebHelper(this.Url);
    w.Queries.Add("cmd", "newdir");
    w.Queries.Add("path", _Path);
    w.Queries.Add("name", name);
    w.Execute(CreateDirectoryResult);
  }
  private void CreateDirectoryResult
  (string stat, string msg, bool allowUp, JsonValue data, object tag)
  {
    if (Complete != null) Complete(this, null);

    if (stat == "ok")
    {
      // update file list
      UpdateFileList();
    }
    else
    {
      ShowError("Error. " + msg);
    }
  }
  #endregion
  #region upload file

  /// <span class="code-SummaryComment"><summary>
</span>  /// Add file to the upload list
  /// <span class="code-SummaryComment"></summary>
</span>  public void AddUploadItem(FileInfo f)
  {
    if (_UploadFiles == null) _UploadFiles = new List<UploadItem>();
    UploadItem itm = new UploadItem(_UploadFiles.Count, f, this.Url, this.Path);
    itm.Complete += new EventHandler(UploadItem_Complete);
    _UploadFiles.Add(itm);
  }

  /// <span class="code-SummaryComment"><summary>
</span>  /// Send upload list to the server
  /// <span class="code-SummaryComment"></summary>
</span>  public void Upload()
  {
    if (_UploadFiles == null || _UploadFiles.Count <= 0) return; // upload list is empty
      
    _UploadErrorMessages = new StringBuilder();

    if (Process!=null) Process(this, null);;

    foreach (UploadItem itm in _UploadFiles)
    {
      itm.Run();//start upload file
    }
  }
  /// <span class="code-SummaryComment"><summary>
</span>  /// Upload file complete handler
  /// <span class="code-SummaryComment"></summary>
</span>  private void UploadItem_Complete(object sender, EventArgs e)
  {
    this.Dispatcher.BeginInvoke(() =>
    {
      UploadItem itm = sender as UploadItem;
      if (itm.State == UploadItem.StateList.Error)
      {
        _UploadErrorMessages.AppendLine(itm.Message);
      }
      // remove file from upload list
      _UploadFiles.Remove(itm);
      if (_UploadFiles.Count == 0)
      {
        // upload list is empty
        // start Complete
        if (Complete != null) Complete(this, null);
        // has error?
        if (_UploadErrorMessages.Length <= 0)
        {
          // no error, update file list
          UpdateFileList();
        }
        else
        {
          // show error message
          ShowError(_UploadErrorMessages.ToString());
        }
      }
    });
  }

  /// <span class="code-SummaryComment"><summary>
</span>  /// FileList Drop handler
  /// <span class="code-SummaryComment"></summary>
</span>  private void FileList_Drop(object sender, DragEventArgs e)
  {
    // add selected files to upload list
    FileInfo[] files = e.Data.GetData(DataFormats.FileDrop) as FileInfo[];
    foreach (FileInfo f in files)
    {
      this.AddUploadItem(f); 
    }

    // upload files
    this.Upload();
  }
  #endregion

  /// <span class="code-SummaryComment"><summary>
</span>  /// The method show error messages
  /// <span class="code-SummaryComment"></summary>
</span>  /// <span class="code-SummaryComment"><param name="msg">Error text</param>
</span>  private void ShowError(string msg)
  {
    this.Dispatcher.BeginInvoke(() =>
    {
      MessageBox.Show(msg, "Error", MessageBoxButton.OK);
    });
  }
}

Using the code

Main files of FileList control: FileList.cs, FileItem.cs, WebHelper.cs and UploadItem.cs (FileManage project). For server - Gateway.cs (FileManager.Common project).

Add FileList to Silverlight page.

<my:FileList Height="256" HorizontalAlignment="Left" 

	Margin="12,41,0,0" x:Name="fileList1" VerticalAlignment="Top" 

	Width="573" Grid.ColumnSpan="2" Grid.RowSpan="2" />

Add the Gateway code to ASP .NET handler (ashx for WebForms) or action (for MVC) and run the server.

FileManager.Common.Gateway myGateway = new FileManager.Common.Gateway();
context.Response.ContentType = "application/json";
context.Response.Write(myGateway.GetResult());

Set Url property for FileList to the Gateway server page.

public MainPage()
{
  InitializeComponent();
  fileList1.Url = "http://localhost:58646/Gateway.ashx"; // you gateway url
  // http://localhost:58646 - is default address for solution but maybe another
}

Enjoy!

License

This article, along with any associated source code and files, is licensed under The Common Public License Version 1.0 (CPL)

Share

About the Author

Alеksey Nemiro
Web Developer Kbyte.Ru
Russian Federation Russian Federation
Started programming in 1998 on the G-Basic and QBasic.

At various times worked with programming languages and technologies: Visaul Basic, Delphi, C, Visual C++, Java, PHP, ASP VBScript and JScript.

Currently engaged in programming based on .NET Framework technologies. Mainly the development of websites on the ASP.NET MVC, C#, TypeScript, SCSS and also database programming (SQL Server and PostgreSQL).

In 2016 started the AdminStock.net - solutions for administrators.

You may also be interested in...

Pro
Pro

Comments and Discussions

 
QuestionMy vote of 5 Pin
liviucatrina8-May-12 21:01
memberliviucatrina8-May-12 21:01 
GeneralMy vote of 5 Pin
pgmckillop9-Jan-12 18:45
memberpgmckillop9-Jan-12 18:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.170915.1 | Last Updated 8 Jan 2012
Article Copyright 2012 by Alеksey Nemiro
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid