Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Textbox Drag/Drop in WPF

, 28 Sep 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
Textbox Drag/Drop in WPF

So last week, somebody posted a question on CodeProject about why a Drag Drop into a TextBox in WPF doesn't actually work. When you attempt to drag and drop an item into a TextBox, it refuses to cooperate and leaves the mouse cursor as the Drop denied cursor and you can't drop into the field. (Incidentally, this behaviour also applies to RichTextBox and FlowDocument controls). The reason that you can't drop into these fields, even if you set AllowDrop to true, is that these particular controls mark drag and drop events as handled, preventing you from handling them yourself.

Now this might seem like a big problem – it certainly makes it look like you can't drag/drop into a textbox, and this would seem to be a huge oversight on Microsoft’s part. Fortunately, with a little bit of knowledge of how WPF handles commands, it’s actually fairly easy to come up with a workaround. Remember that I said that WPF marks these operations as handled? This is the key to being able to work around it – each particular event (such as a DragOver event), also has a corresponding Preview event which we can hook into to perform our processing. Before I show you the code though, the OP posted a follow up query:

“A specific question I have about your solution is that you get the standard mouse cursor with the plus sign inside a box when the drag operation enters the edit box. In my initial solution to the drop into a ListBox I got a mouse cursor with an empty box, not the box with the plus sign. By experimenting I determined that you achieve this with the code you have in the PreviewDrag events. What about that code gets you the cursor with the plus sign, avoiding that anemic cursor without the plus sign?”

The following filename drag/drop sample demonstrates how changing the DragDropEffects parameter changes the appearance of the drop cursor, in answer to the Original Posters followup question:

<Window x:Class="SampleDragDrop.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:sys="clr-namespace:System;assembly=mscorlib"
  Title="Window1" Height="274" Width="300">
  <Window.Resources>
    <ObjectDataProvider
        MethodName="GetValues"
        ObjectType="{x:Type sys:Enum}"
        x:Key="DragProvider">
      <ObjectDataProvider.MethodParameters>
        <x:Type TypeName="DragDropEffects" />
      </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
    <Style TargetType="{x:Type TextBlock}">
      <Setter Property="Margin" Value="3" />
      <Setter Property="VerticalAlignment" Value="Center" />
    </Style>
  </Window.Resources>
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="101*" />
      <ColumnDefinition Width="177*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
      <RowDefinition Height="27*" />
      <RowDefinition Height="203.258*" />
      <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <TextBlock Text="Drag Drop Effects" Grid.Column="0" Grid.Row="0" />
    <TextBlock Text="Drop target" Grid.Column="0" Grid.Row="1" />
    <TextBlock Text="Handled" Grid.Column="0" Grid.Row="2" />
    <ComboBox
      x:Name="cboDropEffects"
      Grid.Row="0"
      Grid.Column="1"
      Margin="2"
      SelectedIndex="0"
      ItemsSource="{Binding Source={StaticResource DragProvider}}" />
    <TextBox
      Grid.Row="1"
      Grid.Column="1"
      Margin="2"
      PreviewDragEnter="TextBox_PreviewDragEnter"
      PreviewDragOver="TextBox_PreviewDragEnter"
      PreviewDrop="TextBox_PreviewDrop" />
    <CheckBox x:Name="chkHandled" IsChecked="True" Grid.Row="2" 
	Grid.Column="1" Margin="2" />
  </Grid>
</Window>

If you look carefully at the code, you see that we bind PreviewDragEnter and the PreviewDragOver to the same event handler. The PreviewDrop event maps to a different event handler, where we actually perform the drop of the filename.

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;

namespace SampleDragDrop
{
  /// <span class="code-SummaryComment"><summary>
</span>  /// Interaction logic for Window1.xaml
  /// <span class="code-SummaryComment"></summary>
</span>  public partial class Window1 : Window
  {
    public Window1()
    {
      InitializeComponent();
    }

    private void TextBox_PreviewDragEnter(object sender, DragEventArgs e)
    {
      e.Effects = (DragDropEffects)cboDropEffects.SelectedItem;
      if (chkHandled.IsChecked.HasValue)
      {
        e.Handled = chkHandled.IsChecked.Value;
      }
    }

    private void TextBox_PreviewDrop(object sender, DragEventArgs e)
    {
      object text = e.Data.GetData(DataFormats.FileDrop);
      TextBox tb = sender as TextBox;
      if (tb != null)
      {
        tb.Text = string.Format("{0}", ((string[])text)[0]);
      }
    }
  }
}

When you run the sample, play around with the Drag Drop Effects values, and setting/unsetting the Handled checkbox, to see what behaviour the textbox exhibits (and the answer to the OPs question, is that setting e.Effects to DragDropEffects.All sets the cursor to the relevant cursor).

This sample is available at SampleDragDrop. Don't forget to change the extension from .doc to .zip when you download it.

License

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

Share

About the Author

Pete O'Hanlon
CEO
United Kingdom United Kingdom
A developer for over 30 years, I've been lucky enough to write articles and applications for Code Project as well as the Intel Ultimate Coder - Going Perceptual challenge. I live in the North East of England with 2 wonderful daughters and a wonderful wife.
 
I am not the Stig, but I do wish I had Lotus Tuned Suspension.
Follow on   Twitter   Google+

Comments and Discussions

 
GeneralMy vote of 5 PinmemberWESTSEYI12-Aug-13 11:16 
QuestionI am boggled!! PinmemberMember 78033551-Jan-13 22:50 
GeneralMy vote of 5 [modified] PinmemberGjelt29-Aug-12 18:04 
GeneralMy vote of 5 PinmemberMember 889799928-May-12 22:25 
GeneralMy vote of 5 Pinmemberdmcmullan7-Jul-10 10:15 
GeneralVery Helpful PinmemberStewBob10-Jun-10 9:01 
GeneralNull Reference Pinmembergeswan28-Sep-09 21:41 
Peter, I get a null reference exception when dropping. It would appear that e.Data.GetData(DataFormats.FileDrop) is returning null.
GeneralRe: Null Reference PinmvpPete O'Hanlon29-Sep-09 8:41 
GeneralRe: Null Reference Pinmembergeswan29-Sep-09 21:10 
GeneralRe: Null Reference PinmvpPete O'Hanlon30-Sep-09 1:51 
GeneralPreview Events Pinmemberaspdotnetdev28-Sep-09 12:12 
GeneralRe: Preview Events PinmvpPete O'Hanlon28-Sep-09 12:18 

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.141022.1 | Last Updated 28 Sep 2009
Article Copyright 2009 by Pete O'Hanlon
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid