Wpf: Drag And Drop To A Textbox
Asked Answered
L

4

45

I've googled this problem, and people have answered similar questions, but for some reason I can't get anything to work. I must have missed something here... At any rate, when I run the following code, the TextBox_DragEnter handler is never called. However, if I change the TextBox element in the xaml to a TextBlock element, it is called. Is there any way to get the same behavior from a TextBox element? The following code completely isolates the problem...

MainWindow.xaml:

<Window x:Class="Wpf1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid Name="myGrid">
        <TextBox AllowDrop="True" PreviewDragEnter="TextBox_DragEnter" PreviewDrop="TextBox_Drop" />
    </Grid>
</Window>

MainWindow.xaml.cs:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Collections.ObjectModel;

namespace Wpf1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void TextBox_DragEnter(object sender, DragEventArgs e)
        {
            e.Effects = DragDropEffects.Copy;
        }

        private void TextBox_Drop(object sender, DragEventArgs e)
        {

        }
    }
}

Many thanks in advance!

Andrew

EDIT:

Just to clarify, I would like to allow dropping a custom object into a textbox. In the Drop handler for the textbox, I would then like to set the text of the textbox to a property in the object, and then set the IsReadOnly property of the TextBox to false. I'm just having some trouble enabling drag and drop for the TextBox...

Lifegiving answered 26/11, 2010 at 0:55 Comment(0)
V
67

If you add a handler for PreviewDragOver, then set e.Handled = true it should work.

Works for me in any case.

Vallo answered 26/11, 2010 at 1:57 Comment(1)
+1 Thanks, worked for me too... Although, then it resets the Effects set in DragEnter event. Need to find some sophisticated way to handle this.Moreno
S
25

TextBox seems to have already some default handling for DragAndDrop. If your data object is a String, it simply works. Other types are not handled and you get the Forbidden mouse effect and your Drop handler is never called.

It seems like you can enable your own handling with e.Handled to true in a PreviewDragOver event handler.

I could not find any details about that at MSDN, but found http://www.codeproject.com/Articles/42696/Textbox-Drag-Drop-in-WPF very helpfull.

Sondrasone answered 18/4, 2014 at 8:42 Comment(0)
P
8

You may also want to handle PreviewDragEnter the same way as PreviewDragOver or it will default to the Forbidden Mouse on the first pixel.

In the handler make sure the DragEventArgs.Data is the type you want to drop. If it is, set DragEventsArgs.Effects to DragDropEffects.Move or something else in AllowedEffects. If it isn't the type you want to drop, set to DragDropEffects.None which disables dropping.

XAML for MVVM Light:

<i:Interaction.Triggers>
        <i:EventTrigger EventName="Drop">
            <cmd:EventToCommand Command="{Binding DragDropCommand}" PassEventArgsToCommand="True" />
        </i:EventTrigger>
        <i:EventTrigger EventName="PreviewDragOver">
            <cmd:EventToCommand Command="{Binding PreviewDragEnterCommand}" PassEventArgsToCommand="True" />
        </i:EventTrigger>
        <i:EventTrigger EventName="PreviewDragEnter">
            <cmd:EventToCommand Command="{Binding PreviewDragEnterCommand}" PassEventArgsToCommand="True" />
        </i:EventTrigger>
    </i:Interaction.Triggers>

Handler in ViewModel:

        private void ExecutePreviewDragEnterCommand(DragEventArgs drgevent)
        {
            drgevent.Handled = true;


            // Check that the data being dragged is a file
            if (drgevent.Data.GetDataPresent(DataFormats.FileDrop))
            {
                // Get an array with the filenames of the files being dragged
                string[] files = (string[])drgevent.Data.GetData(DataFormats.FileDrop);

                if ((String.Compare(System.IO.Path.GetExtension(files[0]), ".xls", true) == 0)
                    && files.Length == 1)
                    drgevent.Effects = DragDropEffects.Move;
                else
                    drgevent.Effects = DragDropEffects.None;

            }
            else
                drgevent.Effects = DragDropEffects.None;
        }
Pulpwood answered 17/9, 2014 at 15:24 Comment(1)
it works, and I make the textbox's text become the file path by set the TextBox's text = files[0]Inapproachable
C
0

Better create your own Textbox class that implements Textbox. Then override the OnDrag-Events and set e.handled to false or do whatever you want.

It's a little dirty to use events that are not made for the original wanted behavior. Preview is to check some stuff and have a good Undo option before committing the real DragDrop-Events.

Coldshoulder answered 7/6, 2018 at 9:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.