Click here to Skip to main content
15,885,546 members
Articles / Desktop Programming / WPF

Wrap Panel Virtualization

Rate me:
Please Sign up or sign in to vote.
4.95/5 (18 votes)
2 Jan 2012CPOL2 min read 53.2K   5.6K   41  
WrapPanel doesn't support virtualization. But we can improve the performance by simulating virtualization.
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using MediaAssistant.Constants;
using MediaAssistant.DAL;
using MediaAssistant.Helper;

namespace MediaAssistant.Management
{
    [Export]
    public class MediaFileScanner : BackgroundScanner
    {
        private List<string> ExistingFiles { get; set; }

        private Queue<string> ScanFolderQueue { get; set; }

        public Dictionary<string, FileSystemWatcher> FileSystemWatchers { get; set; }
        public MediaFileScanner()
        {
            ExistingFiles=new List<string>();
            Name = "Media File Scanner";
            ScanFolderQueue=new Queue<string>();
            FileSystemWatchers=new Dictionary<string, FileSystemWatcher>();
        }
        public override void Stop()
        {
            base.Stop();
            IsScanStarted = false;
            foreach (var fileSystemWatcher in FileSystemWatchers)
            {
                UnsubscribeEvents(fileSystemWatcher.Value);
            }
            FileSystemWatchers.Clear();
        }

        private void UnsubscribeEvents(FileSystemWatcher fileSystemWatcher)
        {
            fileSystemWatcher.Created -= HandleFileCreated;
            fileSystemWatcher.EnableRaisingEvents = false;
            fileSystemWatcher.Dispose();
        }

        public bool IsScanStarted { get; set; }
        protected override void TryToScan()
        {
            if(IsScanStarted)
                return;
            IsScanStarted = true;
            switch (RegistryHelper.ScanOption)
            {
                case ScanOption.SpecificFolder:
                    QueueSpecificFolders();
                    break;
                case ScanOption.MyComputer:
                    foreach (var driveInfo in DriveInfo.GetDrives().Where(driveInfo => driveInfo.IsReady))
                    {
                        Enqueue(driveInfo.RootDirectory.FullName);
                    }
                    break;
                case ScanOption.None:
                    return;
                case ScanOption.MyDocument:
                    Enqueue(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
                    Enqueue(Environment.GetFolderPath(Environment.SpecialFolder.MyMusic));
                    Enqueue(Environment.GetFolderPath(Environment.SpecialFolder.MyVideos));
                    break;
            }
            GetExistingFiles();
            ScanQueuedFolder();
            SetStatusMessage(StatusMessages.Ready);
        }

        private void Enqueue(string fullName)
        {
            Watch(fullName);
            ScanFolderQueue.Enqueue(fullName);
        }

        private void Watch(string fullName)
        {
            if (FileSystemWatchers.ContainsKey(fullName))
                return;
            var watcher = new FileSystemWatcher(fullName);
            SubscribeEvents(watcher);
            //watcher.NotifyFilter = NotifyFilters.FileName;
            watcher.IncludeSubdirectories = true;
            watcher.EnableRaisingEvents = true;
            FileSystemWatchers.Add(fullName,watcher);
        }

        private void SubscribeEvents(FileSystemWatcher watcher)
        {
            watcher.Created += HandleFileCreated;
        }

        private void HandleFileCreated(object sender, FileSystemEventArgs e)
        {
            if (e.ChangeType != WatcherChangeTypes.Created) 
                return;
            
            if(File.Exists(e.FullPath))
                AddFile(e.FullPath);
            else if(Directory.Exists(e.FullPath))
            {
                Scan(e.FullPath);
            }
        }

        private void QueueSpecificFolders()
        {
            foreach (var scannedDirectory in DatabaseManager.Instance.GetScanDirectories())
            {
                if (scannedDirectory.KeepEye == false && scannedDirectory.LastScanned != null)
                {
                    continue;
                }
                if (!Directory.Exists(scannedDirectory.FullPath))
                {
                    continue;
                }
                Enqueue(scannedDirectory.FullPath);
            }  
        }


        private void ScanQueuedFolder()
        {
            while(ScanFolderQueue.Count>0)
            {
                var folderPath = ScanFolderQueue.Dequeue();
                if (!Directory.Exists(folderPath))
                {
                    continue;
                }
                if (Scan(folderPath))
                {
                    var scannedDirectory = DatabaseManager.Instance.GetScanDirectories().FirstOrDefault(d => d.FullPath == folderPath);
                    if(scannedDirectory!=null)
                        DatabaseManager.Instance.MarkAsScanned(scannedDirectory);
                }
                if (ShallReturn())
                    return;
                PauseIfRequested();
            }
        }

        private void GetExistingFiles()
        {
            ExistingFiles=new List<string>();
            ExistingFiles.AddRange(DatabaseManager.Instance.GetImportedFileNames().Where(f => ExistingFiles.Contains(f) == false));
        }

        private bool Scan(string folderPath)
        {
            try
            {
                if (Directory.Exists(folderPath) == false)
                    return false;
                if (ShallReturn())
                    return false;
                PauseIfRequested();
                AddFiles(Directory.GetFiles(folderPath, "*.mp3"));
                if (ShallReturn())
                    return false;
                PauseIfRequested();
                AddFiles(Directory.GetFiles(folderPath, "*.wma"));
                foreach (var extension in Utility.SupportedMovieFileExtension)
                {
                    if (ShallReturn())
                        return false;
                    PauseIfRequested();
                    AddFiles(Directory.GetFiles(folderPath, "*" + extension));
                }
                foreach (var directory in Directory.GetDirectories(folderPath))
                {
                    if (Scan(directory) == false)
                        return false;
                    if (ShallReturn())
                        return false;
                    PauseIfRequested();
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
            
        }

        private void AddFiles(IEnumerable<string> files)
        {
            foreach (var file in files)
            {
                AddFile(file);
                if (ShallReturn())
                    return;
                PauseIfRequested();
            }
        }

        private void AddFile(string fileName)
        {
            if (ExistingFiles.Contains(fileName))
                return;
            ExistingFiles.Add(fileName);
            if (Utility.IsMusicFile(fileName))
            {
                if(DatabaseManager.Instance.IsMusicFileAdded(fileName)==false)
                {
                    SetStatusMessage(string.Format("Adding music file {0}", fileName));
                    DatabaseManager.Instance.AddMusicFile(fileName);
                }
            }
            else if (Utility.IsMovieFile(fileName))
            {
                var fileInfo = new FileInfo(fileName);
                if (fileInfo.Length < Utility.MinMovieFileSize)
                    return;
                if (DatabaseManager.Instance.IsMovieFileAdded(fileName) == false)
                {
                    SetStatusMessage(string.Format("Adding movie file {0}", fileName));
                    DatabaseManager.Instance.AddMovieFile(fileName);
                    DatabaseManager.Instance.UpdateNewMovieTitle(DataSource.Value.ShowDrivesMoviesOnly, DataSource.Value.SelectedProfile);
                    DatabaseManager.Instance.UpdateProcessingTitle(DataSource.Value.ShowDrivesMoviesOnly);
                }
            }
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) KAZ Software Limited
Bangladesh Bangladesh
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions