0

I seem to be having a peculiar problem with drag and dropping button content into a textbox. If I run my program in debug, it only appends the content of the button to the textbox once, but if I run it without debugging it appends twice.

Here is the XAML:

<TextBox x:Name="tbxExpression" Grid.Column="0" Grid.ColumnSpan="2" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Height="50" Margin="5,5,5,47.5" TextAlignment="Right" FontSize="24" Background="#F4F9FD" AllowDrop="True" DragEnter="tbxExpression_Dragging" Drop="tbxExpression_Drop" PreviewDragEnter="tbxExpression_Dragging" PreviewDragOver="tbxExpression_Dragging" DragOver="tbxExpression_Dragging"></TextBox>
<Button x:Name="btnNumOne" Grid.Row="2" Grid.Column="0" Content="1" Margin="5" FontSize="14" Background="#EBF1F6" PreviewMouseLeftButtonDown="button_PreviewMouseLeftButtonDown" MouseMove="button_PreviewMouseMove" PreviewMouseMove="button_PreviewMouseMove"></Button>

And the CS:

private void tbxExpression_Dragging(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent(typeof(string)))
            e.Effects = DragDropEffects.Copy;
        else
            e.Effects = DragDropEffects.None;

        e.Handled = true;
    }
    private void tbxExpression_Drop(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent(typeof(string)))
        {
            // Get the dragged data and place it in textbox.
            string content = e.Data.GetData(typeof(string)).ToString();

            TextBox tbx = (TextBox)sender;
            tbx.AppendText(content);
        }
    }


    // Button Events for Dragging.
    private void button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        startPoint = e.GetPosition(null); // Absolute position.
    }
    private void button_PreviewMouseMove(object sender, MouseEventArgs e)
    {
        if (IsDragging(startPoint, e))
        {
            // Get the dragged button
            Button btn = (Button)sender;

            if (btn != null)
            {
                // Initialize the drag and drop.
                DataObject dragData = new DataObject(typeof(string), btn.Content.ToString());
                DragDrop.DoDragDrop(btn, dragData, DragDropEffects.Copy);
                e.Handled = true;
            }
        }
    }

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

If I drag the content of btnNumOne over to the textbox and drop it, I get "11" in the textbox but if I debug and do the same operation, I only get "1" like it should be. Does anyone know why I could be getting this duplication of text?

Delete
  • 289
  • 1
  • 2
  • 19

2 Answers2

1

You can check how many times it appends the text in Debug by adding the following line

           // Initialize the drag and drop.
                Debug.WriteLine("button_PreviewMouseMove");

That happens two times (you can't put a breakpoint otherwise you loose the drag movement). You may want to change the Drop Event to a PreviewDrop, overwrite the Text of tbx (it is only a workaround, find the effective solution in bold) and set that event as Handled like below

private void tbxExpression_PreviewDrop(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(typeof(string)))
    {
        // Get the dragged data and place it in textbox.
        string content = e.Data.GetData(typeof(string)).ToString();
        Debug.WriteLine("PreviewDrop");
        TextBox tbx = (TextBox)sender;
        tbx.Text = content;
        e.Handled=true;
    }
}

Finally, if you set as Handled the button_PreviewMouseLeftButtonDown as follows, it will append the text only one time :-)

private void button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    Debug.WriteLine("Down");
    startPoint = e.GetPosition(null); // Absolute position.
    e.Handled = true;
}
private void tbxExpression_PreviewDrop(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(typeof(string)))
    {
        // Get the dragged data and place it in textbox.
        string content = e.Data.GetData(typeof(string)).ToString();
        Debug.WriteLine("PreviewDrop: " + String.Join(",",e.Data.GetFormats()));
        TextBox tbx = (TextBox)sender;
        tbx.AppendText(content);
        e.Handled=true;
    }
}
  • Thanks for the help! Your fix worked really well. If I wanted to append text to a specific area of the textbox though and not always to the end, how would I go about that? Find the mouse position at time of drop and do a substring manipulation of what's currently in the textbox? – Delete Mar 09 '15 at 12:14
  • Yesterday, when I tried my code, I was able to drop the "1" at any point and I could even remove the Drop event, so I would say that that part is already managed by the standard TextBox's behaviour. I will come back to this point soon with further comment if I find more about it –  Mar 09 '15 at 13:33
  • Could you maybe post an edit with the full code that you used in your test example? – Delete Mar 09 '15 at 19:28
  • @ Giulio Actually just figured out how you did it, so no need. Thanks again Giulio! – Delete Mar 09 '15 at 19:44
0

Refer the below code. Somehow it is not accepting string format.I changed it to button and it works.

 Point startPoint;
    public MainWindow()
    {
        InitializeComponent();
    }
    private void tbxExpression_Dragging(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent("Button"))
            e.Effects = DragDropEffects.Copy;
        else
            e.Effects = DragDropEffects.None;

        e.Handled = true;
    }
    private void tbxExpression_Drop(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent("Button"))
        {
            // Get the dragged data and place it in textbox.
            var content = (Button)e.Data.GetData("Button");

            TextBox tbx = (TextBox)sender;
            tbx.Text = content.Content.ToString();
        }
    }


    // Button Events for Dragging.
    private void button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        startPoint = e.GetPosition(null); // Absolute position.
    }
    private void button_PreviewMouseMove(object sender, MouseEventArgs e)
    {
        if (IsDragging(startPoint, e))
        {
            // Get the dragged button
            Button btn = (Button)sender;

            if (btn != null)
            {
                // Initialize the drag and drop.
                DataObject dragData = new DataObject("Button", btn);
                DragDrop.DoDragDrop(btn, dragData, DragDropEffects.Copy);
                e.Handled = true;
            }
        }
    }

    // Helper
    private static bool IsDragging(Point dragStart, MouseEventArgs e)
    {
        Vector diff = e.GetPosition(null) - dragStart;
        return e.LeftButton == MouseButtonState.Pressed && (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance || Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance);
    }
Ayyappan Subramanian
  • 5,348
  • 1
  • 22
  • 44