static void

FileGridViewHelper (for Windows.Forms)

Helper to turn an unbound DataGridView into a simple file list. Uses SortableBindingList<T> and FileSizeFormatProvider - An ICustomFormatter for file sizes..

using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
 
namespace Library.Forms
{
    /// <summary>
    /// Helper to turn an unbound DataGridView into a simple file list
    /// </summary>
    public class FileGridViewHelper
    {
        private SortableBindingList<FileInfo> FileList = new SortableBindingList<FileInfo>();
        private DataGridView myGrid;
 
        /// <summary>
        /// Initializes the DataGridView. Call this in Form1_Load.
        /// </summary>
        /// <param name="gv">The DataGridView.</param>
        public void Init(DataGridView gv)
        {
            myGrid = gv;
 
            gv.AllowUserToOrderColumns = true;
            //select a entire row, or a range or rows
            gv.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            gv.MultiSelect = true;
            gv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
 
            gv.AutoGenerateColumns = false;
            DataGridViewTextBoxColumn nameCol = new DataGridViewTextBoxColumn();
            nameCol.Name = "Name";
            nameCol.DataPropertyName = "FullName";
            nameCol.ReadOnly = true;
            nameCol.Width = 200;
            gv.Columns.Add(nameCol);
 
            DataGridViewTextBoxColumn sizeCol = new DataGridViewTextBoxColumn();
            sizeCol.Name = "Size";
            sizeCol.DataPropertyName = "Length";
            sizeCol.ReadOnly = true;
            sizeCol.Width = 50;
            sizeCol.ValueType = typeof(long);
            sizeCol.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
            //formating doesn't work - you have to add CellFormatting event
            sizeCol.DefaultCellStyle.Format = "{0:KB1}";
            sizeCol.DefaultCellStyle.FormatProvider = new FileSizeFormatProvider();
            gv.Columns.Add(sizeCol);
 
            DataGridViewTextBoxColumn extCol = new DataGridViewTextBoxColumn();
            extCol.Name = "Extension";
            extCol.DataPropertyName = "Extension";
            extCol.ReadOnly = true;
            extCol.Width = 50;
            gv.Columns.Add(extCol);
 
            DataGridViewTextBoxColumn modCol = new DataGridViewTextBoxColumn();
            modCol.Name = "Last Changed";
            modCol.DataPropertyName = "LastWriteTime";
            modCol.ReadOnly = true;
            modCol.ValueType = typeof(DateTime);
            gv.Columns.Add(modCol);
 
            BindingSource bs = new BindingSource();
            bs.DataSource = FileList;
            gv.DataSource = bs;
 
            //some events we want to watch
            gv.CellFormatting += gv_CellFormatting; //for custom formatting of file size
            gv.DataBindingComplete += gv_DataBindingComplete; //resize columns
            //gv.DataError += gv_DataError; //for error handling (not used)
            gv.MouseUp += gv_MouseUp; //right click context menu to delete rows
        }
 
        #region private DataGridView events
        //void gv_DataError(object sender, DataGridViewDataErrorEventArgs e)
        //{
        //    DataGridView gv = (DataGridView)sender;
        //    //handle any errors
        //}
 
        void gv_MouseUp(object sender, MouseEventArgs e)
        {
            DataGridView gv = (DataGridView)sender;
            if (e.Button == MouseButtons.Right)
            {
                DataGridView.HitTestInfo hitTestInfo = gv.HitTest(e.X, e.Y);
                if (hitTestInfo.Type == DataGridViewHitTestType.Cell)
                {
                    DataGridViewRow row = gv.Rows[hitTestInfo.RowIndex];
                    if (!row.Selected)
                    {
                        gv.ClearSelection();
                        gv.Rows[hitTestInfo.RowIndex].Selected = true;
                    }
                    ContextMenu cm = new ContextMenu(); //rather than ContextMenuStrip
                    cm.MenuItems.Add("Delete", ContextMenu_Delete);
                    cm.Show(gv, new System.Drawing.Point(e.X, e.Y));
                }
            }
        }
 
        void ContextMenu_Delete(object sender, EventArgs e)
        {
            foreach (DataGridViewRow selectedRow in myGrid.SelectedRows)
            {
                FileInfo fi = selectedRow.DataBoundItem as FileInfo;
                if (fi != null) FileList.Remove(fi);
            }
            myGrid.ClearSelection();
        }
 
        static void gv_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            //because custom formatters aren't honoured
            DataGridView gv = (DataGridView)sender;
            DataGridViewColumn col = gv.Columns[e.ColumnIndex];
            if (col.DefaultCellStyle.FormatProvider is ICustomFormatter)
                e.Value = string.Format(col.DefaultCellStyle.FormatProvider, col.DefaultCellStyle.Format, e.Value);
        }
 
        static void gv_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            DataGridView gv = (DataGridView)sender;
            gv.AutoResizeColumns();
        }
        #endregion
 
        #region Add Files
        /// <summary>
        /// Adds a single file.
        /// </summary>
        /// <param name="filePath">The file path.</param>
        public bool AddFile(string filePath)
        {
            if (!File.Exists(filePath)) return false;
            FileInfo fi = new FileInfo(filePath);
            if (Find(fi.FullName) != null) return false;
            FileList.Add(fi);
            return true;
        }
 
        /// <summary>
        /// Adds a number of files.
        /// </summary>
        /// <param name="filePaths">The file paths.</param>
        public bool AddFiles(string[] filePaths)
        {
            Array.Sort(filePaths);
            foreach (string filePath in filePaths)
            {
                if (!AddFile(filePath)) return false;
            }
            return true;
        }
 
        /// <summary>
        /// Add files with an OpenFileDialog.
        /// </summary>
        /// <param name="directory">The directory (.</param>
        /// <returns></returns>
        /// <example>Use with Application Settings: <code>
        /// Settings.Default.LastDirectory = fileHelper.AddFilesWithDialog(Settings.Default.LastDirectory);
        /// </code></example>
        public string AddFilesWithDialog(string directory)
        {
            using (OpenFileDialog fd = new OpenFileDialog())
            {
                fd.CheckFileExists = true;
                fd.CheckPathExists = true;
                fd.Multiselect = true;
                fd.InitialDirectory = string.IsNullOrEmpty(directory) ?
                    Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) :
                    directory;
 
                DialogResult dr = fd.ShowDialog();
 
                if (dr != DialogResult.OK) return directory;
                if (string.IsNullOrEmpty(fd.FileName)) return directory;
 
                Cursor.Current = Cursors.WaitCursor;
                AddFiles(fd.FileNames);
                Cursor.Current = Cursors.Default;
 
                return Path.GetDirectoryName(fd.FileName);
            }
        }
        #endregion
 
        #region Public access to the file list
        /// <summary>
        /// Finds the specified file path within the list. NB: Contains won't work.
        /// </summary>
        /// <param name="filePath">The file path.</param>
        /// <returns></returns>
        public FileInfo Find(string filePath)
        {
            foreach (FileInfo item in FileList)
            {
                if (item.FullName.Equals(filePath, StringComparison.OrdinalIgnoreCase))
                    return item;
            }
            return null;
        }
 
        /// <summary>
        /// The first file in the list, or null if none. To show previews.
        /// </summary>
        /// <value>The first file.</value>
        public string FirstFile
        {
            get
            {
                if (FileList.Count == 0) return null;
                return FileList[0].FullName;
            }
        }
 
        /// <summary>
        /// Returns an enumerator of the filelist - so you can foreach through them all
        /// </summary>
        public IEnumerable<FileInfo> Files()
        {
            return FileList;
        }
 
        /// <summary>
        /// Clears this file list. Do this after you change the files or our list will be invalid.
        /// </summary>
        public void Clear()
        {
            FileList.Clear();
        }
        #endregion
 
        /// <summary>
        /// Ensures the form supports file drag-drop, putting files into our file list. Call this in Form1_Load.
        /// </summary>
        public void AddFormDragDrop(Form fm)
        {
            //dragdrop props
            fm.AllowDrop = true;
            fm.DragEnter += delegate(object sender, DragEventArgs e)
            {
                if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
                    e.Effect = DragDropEffects.All;
            };
            fm.DragDrop += delegate(object sender, DragEventArgs e)
            {
                string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
                AddFiles(fileList);
            };
        }
    }
}