Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

How to implement simple drag and drop functionality

0.00/5 (No votes)
9 Mar 2003 1  
This article explains how to implement basic drag and drop functionality similar to dragging a text file from Windows explorer and dropping it on the notepad.

Introduction

This article demonstrates the following features :

  1. Drag and Drop functionality
  2. Use of ListBox control and its events.
  3. Use of RichEdit control
  4. Use of System.IO.Directory class.
  5. Use of HelpProvider class for displaying a Help Text for controls on the form when user presses F1.

Using the code

As all of you have seen or used, the basic drag and drop functionality of dragging a text file from the Windows explorer and dropping it on an open instance of notepad, displays the contents of the file. I have implemented a similar functionality to demonstrate the drag and drop functionality using C#. Lets get started.

FileObject

As you can see in the picture above, we will be implementing our own explorer using a listbox and methods of System.IO.Directory class. All of the above directories and files will be represented by one class called FileObject. This class is shown below :

//this class will represent a file/folder and the list will be 

//filled with objects of this class.

public class FileObject
{
    private string fileName;
    private string filePath;
    private bool isFolder;
    //constructor

    public FileObject(string name,bool folder)
    {
        //parse the file name and get the filename without the path.

        string[] pieces = name.Split(new char[]{'\\'});
        fileName = pieces[pieces.Length -1];
        filePath = name;
        isFolder = folder;
    }
    public string Name
    {
        get
        {
            return fileName;
        }
    }
    public string NameWithPath
    {
        get
        {
            return filePath;
        }
    }
    public bool IsFolder
    {
        get
        {
            return isFolder;
        }
    }
    //since we are adding the FileObjects to the list the 

    //list will display the name of each item by calling 

    //its ToString method.Thats why we override it

    //and return the filename/foldername to be shown.

    public override string ToString()
    {
        return fileName;
    }
}

The above class provides simple properties for parsing the filename or foldername. The objects of this class will be added to the list as we navigate from folder to folder.

Explorer using ListBox

Since the ListBox will be acting as our explorer, we have to have the following functionality

  • The user should be able to differentiate between a list item that is a folder from the item which is a file.
  • The user should be able to navigate from folder to folder by double-Clicking on the folder.
  • The user should be able to navigate back to the parent folders.

DrawItem Event

We will implement an eventhandler for the DrawItem event to add the functionality to paint the folder items different from the file items. Here's the code...

//the draw mode has to be OwnerDrawFixed so you can override

//the default drawing of items in the list.

list.MultiColumn  = true;
list.DrawMode     = DrawMode.OwnerDrawFixed;
list.MouseDown   += new MouseEventHandler(this.OnMouseDown);
list.DoubleClick += new EventHandler(this.OnDblClick);
list.DrawItem    += new DrawItemEventHandler(this.OnDrawItem);

The actual OnDrawItem function does the following :

  • If the item being drawn is a folder , paints it bold and red.
  • If the item being drawn is a file,paints in normal black font.
  • Adjust the column width to fit the longest folder/filename.

The code is shown below:

    
void OnDrawItem(object sender, DrawItemEventArgs drawArgs)
{
        
    ListBox lb = (ListBox)sender;
    int index = drawArgs.Index;
    if(index >= 0)
    { 
      //get the current FileObj from the index  

      //retrived from DrawItemEventArgs  FileObject

      obj = (FileObject)lb.Items[index];
      Graphics g = drawArgs.Graphics;
      Font f = new  Font(drawArgs.Font,FontStyle.Bold); 
      //If the FileObject is a folder then paint it red and make it Bold 

      if(obj.IsFolder)
         g.DrawString(obj.Name,f,Brushes.Red,
                      drawArgs.Bounds.Left,drawArgs.Bounds.Top);
      else
         g.DrawString(obj.Name,drawArgs.Font,Brushes.Black,
                      drawArgs.Bounds.Left,drawArgs.Bounds.Top);
      //make sure that the column width as much as the 

      //longest file/folder name 

      if(lb.ColumnWidth <  obj.Name.Length * 10)
            lb.ColumnWidth = obj.Name.Length * 10;
     }
}

DoubleClick Event

We implement a DoubleClick event handler for the listBox which will allow us to navigate into a folder when it is double-Clicked. The code is shown below :

void OnDblClick(object sender,    EventArgs me)
{
    ListBox lb = (ListBox)sender;
    int index = lb.SelectedIndex;
    if(index >= 0)
    {
        FileObject item = (FileObject)lb.Items[index];
        //make sure that the file object is a directory.

        if(item.IsFolder)
        {
            fillList(item.NameWithPath);
        }
    }
}

Back Button

This button when clicked will take us to the parent of the current folder.

void OnPrevClicked(object sender,EventArgs e)
{
    string path = this.Text;
    try{
        DirectoryInfo info = Directory.GetParent(path);
        if(info.FullName != "")
            fillList(info.FullName);
    }
    catch
    {
        prev.Enabled = false;
    }
}

Drag And Drop

Alright, we are almost done. Now this final pice will tie it all together. We will do the following:

  • Start the drag and drop event when the user presses the mouse inside the listBox.
  • Enable the rich edit control to accept the dragged data ONLY if its text or a file dragged from Explorer.

MouseDown Event

We write an eventHandler for MouseDown event in ListBox. When the mouse is pressed, we will :

  1. Make sure the item selected is a File.
  2. Send the file name along with its full path as arguments to DoDragDrop function.

The DoDragDrop function starts the drag and drop process.

void OnMouseDown(object sender,    MouseEventArgs me)
{
    ListBox lb = (ListBox)sender;
    int index = lb.IndexFromPoint(me.X,me.Y) ;
    if(index >= 0)
    {
        FileObject item = (FileObject)lb.Items[index];
        //start the drag and drop operation only if the FileObject represents

        //a file and not a folder.

        if(!item.IsFolder)
           lb.DoDragDrop(item.NameWithPath,DragDropEffects.Copy);
    }
}

DragEnter event

This event is fired when an object is dragged onto the control;the rich edit control in this case.

We will only allow this operation if the dragged data is of type Text or FileDrop (dragged from explorer). The DragDropEffects enumeration allows us to set the effects for the drag and drop operation.

void OnDragEnter(object sender, DragEventArgs de)
{
    if(de.Data.GetDataPresent(DataFormats.Text) || 
       de.Data.GetDataPresent(DataFormats.FileDrop))
    {
        de.Effect = DragDropEffects.Copy;
    }
    else
    {
        de.Effect = DragDropEffects.None;
    }
        
}

DragDrop event

This event is fired after the dragged object has been dropped over the target control.

We will add follwoing functionality to the eventhandler for this event :

  1. Read the data if type is Text from the dropped object. This text will be the file name with path.
  2. If the data is of type FileDrop then retrieve an array of filenames and use the first entry in the array.
  3. Set the label's text to this retrieved text.
  4. Open the file pointed to by this retrieved file name and load its entire contents into the rich edit box.
void OnDragDrop(object sender,DragEventArgs de)
{
    StreamReader read;
    string fileName = "";
    if(de.Data.GetDataPresent(DataFormats.Text)) 
    {
        fileName = (string)de.Data.GetData(DataFormats.Text);
    }
    else if(de.Data.GetDataPresent(DataFormats.FileDrop))
    {
        string[] fileNames;
        fileNames = (string[])de.Data.GetData(DataFormats.FileDrop);
        fileName = fileNames[0];
    }
    fileLabel.Text = fileName;
    read = new StreamReader(fileName);
    string strb = (string)read.ReadToEnd();
    read.Close();
    rich.Text = strb;
}

That's it! We are done implementing Drag and Drop functionality.

Implementing help strings

You can add basic help functionality by adding a HelpProvider control to you form. You can add a helpstring for every control on the form, so that when that control has focus and the user presses F1 key,the form will display the Help text for that control. Here's how you do it...

  • Create a HelpProvider object for the form.
    //implement a help provider for this form.
    
    hlp = new HelpProvider();
  • Set the help string for every control by calling the SetHelpString method of the HelpProvider and passing it your control.
  • Call the SetShowHelp method to enable displaying of help for a control when F1 is pressed.

    hlp.SetHelpString(list,"Shows files and folders in the current folder");
    hlp.SetShowHelp(list,true);
    ....
    ...
    ..
    hlp.SetHelpString(prev,"Click to go to parent folder");
    hlp.SetShowHelp(prev,true);

Running the code

I wrote this code using SharpDevelop. You can just compile the MainForm.cs at command prompt if you dont use an IDE.

  • Run 2 instances of this application and drap the file from one app to richEdit box of the other. You can see the same functionality in use, using just one instance too.
  • Drag a file from Windows Explorer onto the RichEdit box.
  • Type a file name in a text editor like wordpad and drag that text to this box.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here