Click here to Skip to main content
Click here to Skip to main content
Go to top

WPF Drag and Drop MVVM using Behavior

, 12 Jul 2012
Rate this:
Please Sign up or sign in to vote.
WPF Drag and Drop MVVM using Behavior

You can Download the Source Code and see more details on this project here. The goal of this project is to show you how to build a flexible WPF drag and drop application using the MVVM pattern.

We will show you the:

  • Application
  • Design
  • Implementation of the Drag
  • Implementation of the Drop
Please visit here if you like to see more details such as how to do the drop into a ListBox. 

The Application

Below is the application. On the top are the list of Candidates. At the bottom is the company organization chart with the TreeView on the left and the Detailed View on the right. If you are not sure how to setup the organization chart hierarchy be sure to check out the WPF Hierarchy Application.

The application shows you the location on where the item will be dropped with the red dots on each corner (you can easily change the look if you like). You can drag the candidates around to reorder them. Below is before:

after:

You can drag the candidates to the company TreeView. Simply drag the candidate to the new boss that the candidate will be under. Below is before:

after:

You can also drag the candidates to the Detailed View. Below is before:

after:

You can drag the people in the TreeView around. All the children of the dragged element will be reassigned to the dragged element's supervisor. Below is before:

after:

Similarly, you can drag from the TreeView to the Detailed View. Below is before:

after:

You can drag the people in the company TreeView to the Candidates section. Below is before:

after:

You can drag the element in the detailed view around. Below is before:

after:

You can drag the items in the Detailed View to the TreeView. Below is before:

after:

You can drag the people in the company Detailed View to the Candidate section. Below is before:

after:

Below is the class diagram of the application:

Starting from the bottom and going up, In the ViewModel section:

  • The CandidateViewModel can be dragged (you can drag the candidates), so it implements the IDragable
  • The OrgElementViewModel can be dragged and dropped (you can drag and drop into any element in the company organization chart), so it implement both the IDragable and the IDropable
  • The CandidateListViewModel can be dropped (you can drop into the candidate list), so it implements the IDropable
In the Interfaces defined:
  • The IDragable
    • Remove -- Removes the object from the source when the drag and drop occurs. This will be called if it's a move operation and not a copy operation.
    • DataType -- Defines the data type that is dragged
  • The IDropable
    • Drop -- Adds the object to the destination, with the optional parameter on the location to be added (such as when we add a candidate into the candidate section, we need to know the location where the candidate will be dropped)
    • DataType -- Defines the data type that is allowed to be dropped
In the Behavior section:
  • The FrameworkElementDragBehavior -- Performs the actions to start the drag operation by picking up the data. It queries the IDragable interface to record the data type being dragged.
  • The FrameworkElementDropBehavior -- Performs the actions when the drop happens on a FrameworkElement, which is the subclass of System.Windows.UIElement that you commonly see in WPF.
  • The ListBoxDropBehavior -- Performs the actions when an element is dropped onto a ListBox.
In the View:
  • The DetailedView -- Contains the nested controls that shows the organization chart. Since the nested controls are FrameworkElement it will just use the FrameworkElementDragBehavior and the FrameworkElementDropBehavior in the xaml declaration.
  • The TreeView -- Each element in the TreeView are also FrameworkElement, so it will also use the FrameworkElementDragBehavior and the FrameworkElementDropBehavior in the xaml declaration.
  • The CandidateView -- Candidates are displayed using FrameworkElement, so it will use the FrameworkElementDragBehavior for dragging. A candidate is dropped into a ListBox, which requires more details such as the drop location, therefore it will use the ListBoxDropBehavior.
With this setup you can just add the xaml to the View and the drag and drop functionality will come alive:

The main idea on the drag is to pick up the data that will be transferred as well as defining the data type that is transferred.  The data type lets the system tell if the item can be dropped when the mouse moves over a particular area.

In the IDragable interface we have the following:

The DataType property returns the type of the data that is being dragged.

The Remove method removes the source data for a move operation. If it's a copy operation then you simply don't call it. In our application we will only implement the move operation per our business logic, though you can add the copy functionality if you like.

The IDragable interface is implemented in the ViewModel.  In both the CandidateViewModel and the OrgElementViewModel we return the DataType as ElementViewModel:

ElementViewModel is the parent class of both ViewModels, which contains common properties such as the FirstName and the LastName. This allows you to drag items between the two types interchangeably:

The Remove method in the ViewModel simply calls the Model to perform the business logic on removing the element. You can look into the source code if you are interested in the details of the business logic.

Next we define the drag behavior, meaning what would we like to do when a drag occurs. The FrameworkElementDragBehavior class inherits from the System.Windows.Interactivity.Behavior class, which allows you to define the actions that you like to perform for events such as a mouse click or a mouse move. Below is the code:

The AssociatedObject property from the parent class is the UI control in which the behavior is bound to. For example, if we add this behavior to a StackPanel xaml declaration, then the AssociatedObject is the StackPanel.

If the mouse is clicked down (and kept down) and moves out of the area then we start the drag operation. When you have nested controls such as the detailed view of the organization chart this is the most reliable way to detect the drag. If you don't have nested controls you may just use the MouseMove event and check the mouse pressed state from MouseEventArgs.

In the MouseLeave event we check the DataContext of the UI control and see if it implements IDragable. If yes then that means the item can be dragged.  We then get the data type being dragged by calling the IDragable interface and start the drag operation by calling System.Windows.DragDrop.DoDragDrop method.

To enable the drag operation we simply add the xaml to the View for the control that you would like to drag. For example in the TreeView we defined the following to drag the StackPanel from the TreeView:

And the same goes for the Detailed View:

and the CandidateView:

The goal of the drop operation is to:

  • Give visual cues on if the item can be dropped into an area when the mouse hovers over
  • Transfer the data to the destination
  • Remove the data from the source (if it's a move operation and not a copy operation)
Below is our IDropable interface:

The DataType property defines the data type that can be dropped into an area.  Just like the drag operation, we define the DataType that can be dropped as ElementViewModel in the ViewModel so that we can perform drag and drop between the candidate list and the company organization chart:

The Drop method adds the data to the target. The optional index parameter is for the location of the drop such as a ListBox which we will cover in the next section. Since the ViewModel implements this interface, the method simply calls the business logic in the Model. You can look into the source code if you are interested on the business logic implementation.

Next we will look at the FrameworkElementDropBehavior class. Similar to the drag behavior, the FrameworkElementDropBehavior is inherited from the Behavior class, but we define other events that we will handle. Below shows the list of events:

In the DragEnter event we record the data type that can be dropped into this area (so that we can decide the visual cues to give), and we initialize the adorner for displaying the red dots around the corner:

In the DragOver event we will decide if the data type can be dropped. If yes then we need to show the mouse cursor as an item that can be dropped plus drawing the red dots around the corner of the destination by calling the adorner:

In the DragLeave event we remove the red dots around the corner by calling the adorner:

In the Drop event we perform the data transfer. We simply call the Drop method of the IDropable interface to add data to the destination, and call the Remove method of the IDragable interface to remove the data from the source:

And that's all the behavior we need to define. By adding the xaml tags to the View and we can drop the items into any FrameworkElement:

If you would like to see more details on this project please visit here. Although there are a lot more things that you can do, we hope you find this project helpful in implementing your own WPF drag and drop applications.

License

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

Share

About the Author

DotNetLead-SharePoint

United States United States
No Biography provided

Comments and Discussions

 
QuestionDrag and drop between datagrids Pinmembersriveena13-Jul-14 11:46 
QuestionPreview while dragging? PinmemberSuperJMN-CandyBeat1-Mar-13 1:59 
GeneralMy vote of 5 PinmemberDr. Hurol Aslan17-Dec-12 1:39 
QuestionNice! Quick Question Though... Pinmembertomallen3527-Nov-12 0:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140916.1 | Last Updated 13 Jul 2012
Article Copyright 2012 by DotNetLead-SharePoint
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid