2010-11-22 11 views
4

Pour un test simple, je veux faire glisser un bouton vers un TextBox. Je peux commencer à faire glisser le bouton, mais l'événement Drop n'est pas déclenché. Qu'est-ce que je rate?Impossible de faire glisser et déposer WPF simple au travail

Xaml:

<Window x:Class="DayPlanner.View.DnDTest" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="DnDTest" Height="200" Width="200"> 
    <StackPanel> 
     <Button Name="button" 
       Content="OK" 
       PreviewMouseLeftButtonDown="button_PreviewMouseLeftButtonDown" 
       PreviewMouseMove="button_PreviewMouseMove"/> 
     <TextBox Name="textBox" 
       AllowDrop="True" 
       DragEnter="textBox_DragEnter" 
       Drop="textBox_Drop"/> 
    </StackPanel> 
</Window> 

code:

public partial class DnDTest : Window 
{ 
    public DnDTest() 
    { 
     InitializeComponent(); 
    } 

    private Point dragStartPoint; 

    private void button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     dragStartPoint = e.GetPosition(null); 
    } 

    private static bool IsDragging(Point dragStartPoint, MouseEventArgs e) 
    { 
     var diff = e.GetPosition(null) - dragStartPoint; 
     return 
      e.LeftButton == MouseButtonState.Pressed && 
      (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance || 
       Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance); 
    } 

    private void button_PreviewMouseMove(object sender, MouseEventArgs e) 
    { 
     if (IsDragging(dragStartPoint, e)) 
     { 
      DragDrop.DoDragDrop(button, new DataObject("Button", button), DragDropEffects.Move); 
      e.Handled = true; 
     } 
    } 

    private void textBox_DragEnter(object sender, DragEventArgs e) 
    { 
     e.Handled = true; 
    } 

    private void textBox_Drop(object sender, DragEventArgs e) 
    { 
     var button = (Button)e.Data.GetData("Button"); 
     textBox.Text = string.Format("[0]", button.Content.ToString()); 
     e.Handled = true; 
    } 
} 
+0

Vous ne définissez pas l'effet de traînée. Quelque chose comme e.Effects = DragDropEffects.Copy; dans votre gestionnaire DragEnter fonctionnerait. – genus

Répondre

2

Cela peut être un cas étrange, mais pour le réparer, j'ai dû gérer ou faire glisser des événements, y compris les versions d'aperçu.

Voici comment le faire fonctionner.

Xaml:

<Window x:Class="DayPlanner.View.DnDTestBasic" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="DnDTestBasic" Height="200" Width="200"> 
    <StackPanel> 
     <Button Name="button" 
       Content="OK" 
       PreviewMouseLeftButtonDown="button_PreviewMouseLeftButtonDown" 
       PreviewMouseMove="button_PreviewMouseMove"/> 
     <TextBox Name="textBox" 
       AllowDrop="True" 
       PreviewDragEnter="textBox_Dragging" 
       DragEnter="textBox_Dragging" 
       PreviewDragOver="textBox_Dragging" 
       DragOver="textBox_Dragging" 
       Drop="textBox_Drop"/> 
     <TextBlock Name="status" 
        Text="No dragging"/> 
    </StackPanel> 
</Window> 

code:

public partial class DnDTestBasic : Window 
{ 
    public DnDTestBasic() 
    { 
     InitializeComponent(); 
    } 

    private Point dragStartPoint; 

    private void button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     dragStartPoint = e.GetPosition(null); 
     status.Text = "New drag start position"; 
    } 

    private static bool IsDragging(Point dragStartPoint, MouseEventArgs e) 
    { 
     var diff = e.GetPosition(null) - dragStartPoint; 
     return 
      e.LeftButton == MouseButtonState.Pressed && 
      (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance || 
      Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance); 
    } 

    private void button_PreviewMouseMove(object sender, MouseEventArgs e) 
    { 
     if (IsDragging(dragStartPoint, e)) 
     { 
      status.Text = "Starting drag..."; 
      DragDrop.DoDragDrop(button, new DataObject("Button", button), DragDropEffects.Copy); 
      status.Text = "Dragging done."; 
      e.Handled = true; 
     } 
    } 

    private void textBox_Dragging(object sender, DragEventArgs e) 
    { 
     if (e.Data.GetDataPresent("Button")) 
      e.Effects = DragDropEffects.Copy; 
     else 
      e.Effects = DragDropEffects.None; 
     e.Handled = true; 
    } 

    private void textBox_Drop(object sender, DragEventArgs e) 
    { 
     var button = (Button)e.Data.GetData("Button"); 
     textBox.Text = string.Format("[{0}]", button.Content.ToString()); 
     e.Handled = true; 
    } 
} 
+0

+1, ce fut une aide précieuse . Pour moi, ce qui me manquait était le 'new DataObject (...)' - auparavant j'utilisais un objet directement, avec son 'Type' comme clé, ce qui apparemment ne fonctionne pas :-) – Cameron

2

Je crois qu'il doit faire avec le fait que lorsque vous démarrez l'événement de déplacement, la commande de bouton capture d'entrée de la souris. Les mouvements de la souris que vous faites après sont enregistrés sur le bouton au lieu de l'application

J'ai rencontré un problème similaire et j'ai fini par utiliser les événements MouseEnter/Leave à la place de l'environnement WPF drag/drop intégré.

+0

Salut, j'ai scénario similaire est là toute référence que je peux regarder. – Eldho

+0

@Eldho [Cette réponse] (http://stackoverflow.com/a/2639399/302677) sur SO m'a beaucoup aidé à aller dans la bonne direction – Rachel

+0

Merci, Mais le mien est différent, j'ai deux DataGrid dont 1 contient bouton et bouton bascule, je veux glisser-déposer la ligne entière à la grille de données 2ème. Le problème est que je ne pouvais pas faire glisser lorsque la sélection sur BUTTON/CHECKBOX de la RANG, sélectionnant SEULEMENT sur la bordure fait le travail de glissement, je veux faire glisser la ligne entière même en cliquant sur le bouton. – Eldho