web-dev-qa-db-fra.com

Wpf: glisser-déposer dans une zone de texte

J'ai cherché ce problème dans Google et les gens ont répondu à des questions similaires, mais pour une raison quelconque, je ne peux rien faire fonctionner. J'ai dû manquer quelque chose ici ... En tout cas, lorsque j'exécute le code suivant, le gestionnaire TextBox_DragEnter n'est jamais appelé. Cependant, si je change l'élément TextBox du xaml en un élément TextBlock, il est appelé. Est-il possible d'obtenir le même comportement à partir d'un élément TextBox? Le code suivant isole complètement le problème ...

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)
        {

        }
    }
}

Merci d'avance!

Andrew

MODIFIER:

Juste pour clarifier, je voudrais permettre de déposer un objet personnalisé dans une zone de texte. Dans le gestionnaire Drop de la zone de texte, je souhaite ensuite définir le texte de la zone de texte sur une propriété de l'objet, puis définir la propriété IsReadOnly de la zone de texte sur false. J'ai juste du mal à activer le glisser-déposer pour la zone de texte ...

27
Andrew

Si vous ajoutez un gestionnaire pour PreviewDragOver, définissez e.Handled = true pour que cela fonctionne.

Fonctionne pour moi en tout cas.

49
Liz

TextBox semble déjà avoir une gestion par défaut pour DragAndDrop. Si votre objet de données est une chaîne, cela fonctionne simplement. Les autres types ne sont pas gérés et vous obtenez l'effet Forbidden mouse et votre gestionnaire Drop n'est jamais appelé.

Il semble que vous puissiez activer votre propre gestion avec e.Handled à true dans un gestionnaire d'événements PreviewDragOver.

Je n'ai pu trouver aucun détail à ce sujet chez MSDN, mais A trouvé http://www.codeproject.com/Articles/42696/Textbox-Drag-Drop-DW-F très utile.

13
trapicki

Vous pouvez également vouloir gérer PreviewDragEnter de la même manière que PreviewDragOver ou utiliser par défaut la souris interdite sur le premier pixel.

Dans le gestionnaire, assurez-vous que DragEventArgs.Data est le type que vous souhaitez supprimer. Si c'est le cas, définissez DragEventsArgs.Effects sur DragDropEffects.Move ou quelque chose d'autre dans AllowedEffects. Si ce n'est pas le type que vous voulez supprimer, définissez-le sur DragDropEffects.Aucune qui désactive la suppression. 

XAML pour 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>

Gestionnaire dans 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;
        }
4
haps

Mieux créer votre propre classe Textbox qui implémente Textbox. Ensuite, remplacez OnDrag-Events et définissez e.handled sur false ou faites ce que vous voulez.

Il est un peu sale d’utiliser des événements qui ne sont pas conçus pour le comportement recherché initial. Aperçu consiste à vérifier certaines choses et à avoir une bonne option d'annulation avant de valider les véritables DragDrop-Events.

0
Tost