Click here to Skip to main content
15,896,502 members
Articles / Desktop Programming / WPF

Very Simple WPF Drag and Drop Sample without Win32 Calls

Rate me:
Please Sign up or sign in to vote.
4.23/5 (17 votes)
16 Mar 2008CPOL2 min read 146.3K   4.5K   38  
Drag and Drop sample without P/Invoke
// Copyright Nick Polyak 2008

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;

namespace DragDropTest
{
    // delegate for GetPosition function of DragEventArgs and
    // MouseButtonEventArgs event argument objects. This delegate is used to reuse the code
    // for processing both types of events.
    delegate Point GetPositionDelegate(IInputElement element);

    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        int oldIndex = -1;

        public Window1()
        {
            InitializeComponent();

            ListView1.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(ListView1_PreviewMouseLeftButtonDown);
            ListView1.Drop += new DragEventHandler(ListView1_Drop);
        }

        // function called during drop operation
        void ListView1_Drop(object sender, DragEventArgs e)
        {
            if (oldIndex < 0)
                return;

            int index = this.GetCurrentIndex(e.GetPosition);

            if (index < 0)
                return;

            if (index == oldIndex)
                return;

            Shapes myShapes = Resources["MyShapes"] as Shapes;

            Shape movedShape = myShapes[oldIndex];
            myShapes.RemoveAt(oldIndex);

            myShapes.Insert(index, movedShape);
        }

        void ListView1_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            oldIndex = this.GetCurrentIndex(e.GetPosition);

            if (oldIndex < 0)
                return;

            ListView1.SelectedIndex = oldIndex;
            Shape selectedItem = this.ListView1.Items[oldIndex] as Shape;

            if (selectedItem == null)
                return;

            // this will create the drag "rectangle"
            DragDropEffects allowedEffects = DragDropEffects.Move;
            if (DragDrop.DoDragDrop(this.ListView1, selectedItem, allowedEffects) != DragDropEffects.None)
            {
                // The item was dropped into a new location,
                // so make it the new selected item.
                this.ListView1.SelectedItem = selectedItem;
            }
        }

        ListViewItem GetListViewItem(int index)
        {
            if (ListView1.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
                return null;

            return ListView1.ItemContainerGenerator.ContainerFromIndex(index) as ListViewItem;
        }

        // returns the index of the item in the ListView
        int GetCurrentIndex(GetPositionDelegate getPosition)
        {
            int index = -1;
            for (int i = 0; i < this.ListView1.Items.Count; ++i)
            {
                ListViewItem item = GetListViewItem(i);
                if (this.IsMouseOverTarget(item, getPosition))
                {
                    index = i;
                    break;
                }
            }
            return index;
        }

        bool IsMouseOverTarget( Visual target, GetPositionDelegate getPosition)
		{
			Rect bounds = VisualTreeHelper.GetDescendantBounds( target );
			Point mousePos = getPosition((IInputElement) target);
			return bounds.Contains( mousePos );
		}
    }
}

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
Architect AWebPros
United States United States
I am a software architect and a developer with great passion for new engineering solutions and finding and applying design patterns.

I am passionate about learning new ways of building software and sharing my knowledge with others.

I worked with many various languages including C#, Java and C++.

I fell in love with WPF (and later Silverlight) at first sight. After Microsoft killed Silverlight, I was distraught until I found Avalonia - a great multiplatform package for building UI on Windows, Linux, Mac as well as within browsers (using WASM) and for mobile platforms.

I have my Ph.D. from RPI.

here is my linkedin profile

Comments and Discussions