// Copyright (c) 2010
// by OpenLight Group
// http://openlightgroup.net/
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
//
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// ****************************************************************************
// Major portions from Silverlight File Upload
// http://silverlightfileupld.codeplex.com/
// By darick_c
// http://www.codeplex.com/site/users/view/darick_c
//
using System;
using System.ComponentModel;
using System.Windows.Input;
using System.Collections.ObjectModel;
using MVMFileManager.FileManager;
using System.Windows;
using System.IO;
using MVMFileManager;
using System.Linq;
namespace MVVMFileManager
{
public class MainViewModel : INotifyPropertyChanged
{
private UIElement DropUIElement;
private double DropUIElementOpacity;
public event RoutedEventHandler UploadComplete;
public int MaxConcurrentUploads { get; set; }
public long UploadChunkSize { get; set; }
public bool ResizeImage { get; set; }
public int ImageSize { get; set; }
public string Filter { get; set; }
public bool Multiselect { get; set; }
public Uri UploadUrl { get; set; }
private bool uploading { get; set; }
private long TotalUploadSize { get; set; }
private long TotalUploaded { get; set; }
public long MaximumTotalUpload { get; set; }
public long MaximumUpload { get; set; }
public int MaxNumberToUpload { get; set; }
public ObservableCollection<FileUpload> files;
public MainViewModel()
{
// Set the command property
SetFilesCommand = new DelegateCommand(SetFiles, CanSetFiles);
SetDropUIElementCommand = new DelegateCommand(SetDropUIElement, CanSetDropUIElement);
// Set default values
SilverlightFolders = new ObservableCollection<SilverlightFolder>();
SilverlightFiles = new ObservableCollection<SilverlightFile>();
UploadChunkSize = 4194304;
MaximumTotalUpload = 9999999999999;
MaximumUpload = 9999999999999;
ResizeImage = false;
FileUploadingProperty = false;
// Pass a reference of this class to the method to get the Folders
SilverlightFolderAndFiles objSilverlightFolderAndFiles = new SilverlightFolderAndFiles();
objSilverlightFolderAndFiles.GetFolders(this);
}
// Commanding
#region SetFilesCommand
public ICommand SetFilesCommand { get; set; }
public void SetFiles(object param)
{
// Get the Folder selected
SelectedSilverlightFolder = (SilverlightFolder)param;
// Clear the file list
SilverlightFiles = new ObservableCollection<SilverlightFile>();
// Pass a reference of this class to the method to get the Files
SilverlightFolderAndFiles objSilverlightFolderAndFiles = new SilverlightFolderAndFiles();
objSilverlightFolderAndFiles.GetFiles(this, SelectedSilverlightFolder);
}
private bool CanSetFiles(object param)
{
return true;
}
#endregion
#region SetDropUIElementCommand
public ICommand SetDropUIElementCommand { get; set; }
public void SetDropUIElement(object param)
{
// Set the UI Element to be the drop point for files
DropUIElement = (UIElement)param;
// Save the opacity of the element
DropUIElementOpacity = DropUIElement.Opacity;
// Turn on allow drop
DropUIElement.AllowDrop = true;
// Attach event handlers
DropUIElement.DragOver += new DragEventHandler(DropUIElement_DragOver);
DropUIElement.DragLeave += new DragEventHandler(DropUIElement_DragLeave);
DropUIElement.Drop += new DragEventHandler(DropUIElement_Drop);
}
private bool CanSetDropUIElement(object param)
{
return true;
}
void DropUIElement_DragOver(object sender, DragEventArgs e)
{
// Only allow drop if not uploading
if (FileUploadingProperty == false)
{
// If you hover over the drop point, change it's opacity so users will
// have some indication that they can drop
DropUIElement.Opacity = (double)0.5;
}
}
void DropUIElement_DragLeave(object sender, DragEventArgs e)
{
// Return opacity to normal
DropUIElement.Opacity = DropUIElementOpacity;
}
#endregion
// Upload File
#region DropUIElement_Drop
void DropUIElement_Drop(object sender, DragEventArgs e)
{
// Only allow drop if not uploading
if (FileUploadingProperty == false)
{
// Return opacity to normal
DropUIElement.Opacity = DropUIElementOpacity;
// If there is something being dropped upload it
if (e.Data != null)
{
FileInfo[] Dropfiles = e.Data.GetData(DataFormats.FileDrop) as FileInfo[];
files = new ObservableCollection<FileUpload>();
// Get the upload URL
string strURLWithSelectedFolder = string.Format("{0}?folder={1}", GetWebserviceAddress(), SelectedSilverlightFolder.FullPath);
Uri uri = new Uri(strURLWithSelectedFolder, UriKind.Absolute);
UploadUrl = uri;
foreach (FileInfo fi in Dropfiles)
{
// Create an FileUpload object
FileUpload upload = new FileUpload(App.Current.RootVisual.Dispatcher, UploadUrl, fi);
if (UploadChunkSize > 0)
{
upload.ChunkSize = UploadChunkSize;
}
if (MaximumTotalUpload >= 0 && TotalUploadSize + upload.FileLength > MaximumTotalUpload)
{
MessageBox.Show("You have exceeded the total allowable upload amount.");
break;
}
if (MaximumUpload >= 0 && upload.FileLength > MaximumUpload)
{
MessageBox.Show(string.Format("The file '{0}' exceeds the maximun upload size.", upload.Name));
break;
}
// Wire up handles for status changed and upload percentage
// These will be updating the properties that the ViewModel exposes
upload.StatusChanged += new EventHandler(upload_StatusChanged);
upload.UploadProgressChanged += new ProgressChangedEvent(upload_UploadProgressChanged);
// Start the Upload
upload.Upload();
}
}
}
}
#endregion
#region UploadFiles
private void UploadFiles()
{
uploading = true;
while (files.Count(f => f.Status == FileUploadStatus.Uploading || f.Status == FileUploadStatus.Resizing) < MaxConcurrentUploads && uploading)
{
if (files.Count(f => f.Status != FileUploadStatus.Complete && f.Status != FileUploadStatus.Uploading && f.Status != FileUploadStatus.Resizing) > 0)
{
FileUpload fu = files.First(f => f.Status != FileUploadStatus.Complete && f.Status != FileUploadStatus.Uploading && f.Status != FileUploadStatus.Resizing);
fu.Upload();
}
else if (files.Count(f => f.Status == FileUploadStatus.Uploading || f.Status == FileUploadStatus.Resizing) == 0)
{
uploading = false;
// Raise completed event
if (UploadComplete != null)
{
UploadComplete(this, new RoutedEventArgs());
}
}
else
{
break;
}
}
}
#endregion
// Uploading Events
#region upload_UploadProgressChanged
void upload_UploadProgressChanged(object sender, UploadProgressChangedEventArgs args)
{
// Update the progress percentage
FileuploadPercentProperty = args.ProgressPercentage.ToString();
}
#endregion
#region upload_StatusChanged
void upload_StatusChanged(object sender, EventArgs e)
{
FileUpload fu = sender as FileUpload;
FileUploadingProperty = (fu.Status == FileUploadStatus.Uploading);
if (fu.Status == FileUploadStatus.Complete)
{
// Refresh files for te selected folder
SetFiles(SelectedSilverlightFolder);
}
}
#endregion
// Utility
#region GetFileSize
private string GetFileSize(long length)
{
double bytes = (double)length;
string fileSize = "0 KB";
if (bytes >= 1073741824)
fileSize = String.Format("{0:##.##}", bytes / 1073741824) + " GB";
else if (bytes >= 1048576)
fileSize = String.Format("{0:##.##}", bytes / 1048576) + " MB";
else if (bytes >= 1024)
fileSize = String.Format("{0:##.##}", bytes / 1024) + " KB";
else if (bytes > 0 && bytes < 1024)
fileSize = "1 KB";
return fileSize;
}
#endregion
#region GetWebserviceAddress
private string GetWebserviceAddress()
{
string strXapFile = @"/ClientBin/MVMFileManager.xap";
string strBaseWebAddress =
App.Current.Host.Source.AbsoluteUri.Replace(strXapFile, "");
return string.Format(@"{0}/{1}", strBaseWebAddress, @"WebService/FileUpload.ashx");
}
#endregion
// Properties
#region FileUploadingProperty
private bool _FileUploadingProperty;
public bool FileUploadingProperty
{
get
{
return this._FileUploadingProperty;
}
set
{
this._FileUploadingProperty = value;
this.NotifyPropertyChanged("FileUploadingProperty");
}
}
#endregion
#region FileuploadPercentProperty
private string _FileuploadPercentProperty;
public string FileuploadPercentProperty
{
get
{
return string.Format("Uploading {0} %", this._FileuploadPercentProperty);
}
set
{
this._FileuploadPercentProperty = value;
this.NotifyPropertyChanged("FileuploadPercentProperty");
}
}
#endregion
// Collections
#region Folders
private ObservableCollection<SilverlightFolder> _SilverlightFolders;
public ObservableCollection<SilverlightFolder> SilverlightFolders
{
get { return _SilverlightFolders; }
private set
{
if (SilverlightFolders == value)
{
return;
}
_SilverlightFolders = value;
this.NotifyPropertyChanged("SilverlightFolders");
}
}
#endregion
#region SelectedSilverlightFolder
private SilverlightFolder _SelectedSilverlightFolder;
public SilverlightFolder SelectedSilverlightFolder
{
get { return _SelectedSilverlightFolder; }
set
{
if (SelectedSilverlightFolder == value)
{
return;
}
_SelectedSilverlightFolder = value;
this.NotifyPropertyChanged("SelectedSilverlightFolder");
}
}
#endregion
#region Files
private ObservableCollection<SilverlightFile> _SilverlightFiles;
public ObservableCollection<SilverlightFile> SilverlightFiles
{
get { return _SilverlightFiles; }
private set
{
if (SilverlightFiles == value)
{
return;
}
_SilverlightFiles = value;
this.NotifyPropertyChanged("SilverlightFiles");
}
}
#endregion
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
#endregion
}
}