Click here to Skip to main content
15,867,141 members
Articles / Desktop Programming / WPF
Tip/Trick

[How to] Listen to your DragEventArgs!

Rate me:
Please Sign up or sign in to vote.
1.00/5 (1 vote)
12 Apr 2017CPOL2 min read 10.5K   1   2
How to wire up drag+drop events through multiple objects.

The Problem

Handling just about anything in code-behind is bad (generally speaking) and can very easily create tightly coupled dependencies.  Handling events, like drag+drop, in code-behind makes it even easier to produce these dependencies.

So how do you handle drop events if it's not in the code-behind?

The Solution (sample code)

Quick FYI - I just figured this out and wanted to share!  There are most likely better ways to handle or go about solving this, so let me know in the comments if you know any.

 

I find examples to be the best way for me to explain a concept.  Let's say you have a UserControl, we'll call it MyView, that has the initial drop event defined.  We also have the main window class (MainWindow) that will have MyView as a child element .  In this example the MainWindow will listen to the Drop event of MyView and subsequently call a method of it's ViewModel (MainWindowViewModel) to handle the logic.

Keep in mind that the point of this tip/trick is only to show how to enable listening to an event that uses DragEventArgs (like Drop or DragEnter).  Where you actually listen from is up to you.

UserControl MyView:

MyView.xaml
XML
<UserControl x:Class="MyProject.Views.MyView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300"
             x:Name="uc_View">
    <Grid>
        <ListBox Name="lbxView" AllowDrop="True" Drop="lbxView_Drop">
            <!-- Add listbox content here -->
        </ListBox>
    </Grid>
</UserControl>

Key code:

AllowDrop basically enables the drag/drop.

Drop is where we give the method name that will be called on a drop event.

 

MyView.xaml.cs
C#
using System;
using System.Windows;
using System.Windows.Controls;

namespace MyProject.Views
{
    /// <summary>
    /// Interaction logic for MyView.xaml
    /// </summary>
    public partial class MyView : UserControl
    {
        // Define an 'EventHandler' for an object to listen to.
        // The name doesn't really matter, just know that this is what other
        // objects will reference when adding their listener.
        public event EventHandler<DragEventArgs> ObjectDropped;
        
        // Define how to invoke/call this event
        protected virtual void OnObjectDropped(DragEventArgs e)
        {
            ObjectDropped?.Invoke(this, e);
        }
        
        // Define the drop method that we specified in the MyView.xaml file
        private void lbxView_Drop(object sender, DragEventArgs e)
        {
            OnObjectDropped(sender, e);
        }
    }
}

Key code:

EventHandler<> we need to use the template version of the EventHandler in order for this to work.  This is also the public handle for other objects to add their listening method.

lbxView_Drop is fired on the drop event and essentially calls the listening delegates.

 

Window MainWindow:

MainWindow.xaml
XML
<Window x:Class="MyProject.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:MyProject"
        xmlns:localViews="clr-namespace:MyProject.Views"
        Title="MyApp" Height="500" Width="720">
    <Grid>
        <localViews:MyView x:Name="myView" ObjectDropped="MyView_ObjectDropped"/>
    </Grid>
</Window>

Key code:

ObjectDropped is that public event handle I mentioned earlier.  This is where you pass in the listening method name.

MainWindow.xaml.cs
C#
using System.Windows;
using MyProject.ViewModels;

namespace MyProject
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        // Just for a simple demonstration of passing the logic to the ViewModel
        private MainWindowViewModel _viewModel;
        
        private void MyView_ObjectDropped(object sender, DragEventArgs e)
        {
            // Handle the drop logic here!
            // Example:
            _viewModel.ObjectDropped( sender, e );
        }
    }
}

There's not really any key code here and is mainly here for completeness.  Yes, the handling of the ViewModel could be abstracted away, but that's out of the scope of this article.


Window MainWindow (alternate):

I strongly advise against this, but I know that what follows may be the best option for someone else.

The other way you can add the listener is to omit the ObjectDropped="MyView_ObjectDropped" in MainWindow.xaml and add the listener from the MainWindow's constructor.

MainWindow.xaml.cs (alternate)
C#
using System.Windows;

namespace MyProject
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            myView.ObjectDropped += new EventHandler<DragEventArgs>(MyView_ObjectDropped);
        }
            
        private void MyView_ObjectDropped(object sender, DragEventArgs e)
        {
            // Handle the drop logic here!
        }
    }
}

License

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


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionI'm confused. Pin
Pete O'Hanlon10-Apr-17 21:11
subeditorPete O'Hanlon10-Apr-17 21:11 
AnswerRe: I'm confused. Pin
Dave “DWC” Curry11-Apr-17 14:27
Dave “DWC” Curry11-Apr-17 14:27 
I guess I got a little too excited and didn't specify the focus well enough. I'll make some edits next time I get a chance.

I'll look into behaviors, though. Thanks for the suggestion!

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

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