简体   繁体   中英

Drag And Drop Not Working In ScrollViewer

My problem is the drag and drop of border become not workin when I wrap the canvas inside the scrollviewer.

1200x1200 canvas put in the 500x500 scrollviewer. I want the canvas is scrollable (touch slide) in the scrollviewer. The drag and drop in canvas is working perfectly before I insert in the scrollviewer.

MainWindow.xaml

<Grid ClipToBounds="True">
        <ScrollViewer Name="scbb" Width="500" Height="500" HorizontalScrollBarVisibility="Hidden" 
            VerticalScrollBarVisibility="Hidden" HorizontalAlignment="Left"  
            VerticalAlignment="Top" Background="LightBlue" ScrollViewer.CanContentScroll="True">
        <Canvas x:Name="canvas" Width="1200" Height="1200"
            MouseLeftButtonDown="CanvasMouseLeftButtonDown"
            MouseLeftButtonUp="CanvasMouseLeftButtonUp"
            MouseMove="CanvasMouseMove">
        </Canvas>
        </ScrollViewer>
        <Button x:Name="btnEnable" Content="Enable" Height="50" Width="50" Margin="0,0,115,10" VerticalAlignment="Bottom" 
            HorizontalAlignment="Right" Click="btnEnable_Click"/>
        <Button Content="Add Image" Width="100" Height="100" VerticalAlignment="Bottom" 
            HorizontalAlignment="Right" Click="AddButtonClick" Margin="0,0,10,10"/>
    </Grid>

MainWindow.xaml.cs

private void AddButtonClick(object sender, RoutedEventArgs e)
        {
            int iNum = SETTING.GetTableRunningNumber();

            var borderWrap = new Border();
            borderWrap.Width = 100;
            borderWrap.Height = 100;
            borderWrap.Background = Brushes.Green;

            var label1 = new Label();
            label1.VerticalAlignment = VerticalAlignment.Center;
            label1.HorizontalAlignment = HorizontalAlignment.Center;
            label1.Content = "Table " + iNum.ToString();
            label1.Name = "Table" + iNum.ToString();
            label1.Foreground = Brushes.White;
            label1.FontWeight = FontWeights.Bold;

            borderWrap.Child = label1;
            borderWrap.MouseDown += TableMouseDown;

            Canvas.SetLeft(borderWrap, 10);
            Canvas.SetTop(borderWrap, 10);
            canvas.Children.Add(borderWrap);

            iNum += 1;
            SETTING.SetTableRunningNumber(iNum);
        }

        private Point mousePosition;
        private Border draggedBorder;

        private void TableMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (!SETTING.GetEnableDrag())
            {
                var cLabel = e.Source as Label;
                var bBorder = e.Source as Border;

                if (cLabel != null)
                {
                    MessageBox.Show(cLabel.Name.ToString());
                }
            }
        }

        private void CanvasMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (SETTING.GetEnableDrag())
            {
                var dBorder = e.Source as Border;
                var cLabel = e.Source as Label;

                if (dBorder == null)
                {
                    dBorder = (Border)cLabel.Parent;
                }

                if (dBorder != null && canvas.CaptureMouse())
                {
                    mousePosition = e.GetPosition(canvas);
                    draggedBorder = dBorder;
                    Panel.SetZIndex(draggedBorder, 1);
                }
            }           
        }

        async Task PutTaskDelay100()
        {
            await Task.Delay(100);
        }

        private async void CanvasMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (SETTING.GetEnableDrag())
            {
                await PutTaskDelay100();
                if (draggedBorder != null)
                {
                    canvas.ReleaseMouseCapture();
                    Panel.SetZIndex(draggedBorder, 0);
                    draggedBorder = null;
                }

            }
        }

        private void CanvasMouseMove(object sender, MouseEventArgs e)
        {
            if (SETTING.GetEnableDrag())
            {
                double canvasSize = 1200;
                if (draggedBorder != null)
                {
                    var position = e.GetPosition(canvas);
                    var offset = position - mousePosition;
                    mousePosition = position;

                    double newTop = Canvas.GetTop(draggedBorder) + offset.Y;
                    double newLeft = Canvas.GetLeft(draggedBorder) + offset.X;

                    if (newTop < 0)
                    {
                        newTop = 0;
                    }
                    else if (newTop + draggedBorder.ActualWidth > canvasSize)
                        newTop = canvasSize - draggedBorder.ActualWidth;

                    if (newLeft < 0)
                    {
                        newLeft = 0;
                    }
                    else if (newLeft + draggedBorder.ActualWidth > canvasSize)
                        newLeft = canvasSize - draggedBorder.ActualWidth;

                    Canvas.SetLeft(draggedBorder, newLeft);
                    Canvas.SetTop(draggedBorder, newTop);
                }
            }       
        }

I had the problem months ago and solved it in the code behind with these additions.

After the InitializeComponent in the WindowMain.xaml.cs add:

    public WindowMain()
{
    InitializeComponent();

    // your code, etc.

    scrollViewer.AllowDrop = true;
    scrollViewer.PreviewDragEnter += scrollViewer_PreviewDragEnter;
    scrollViewer.PreviewDragOver += scrollViewer_PreviewDragOver;
    scrollViewer.Drop += scrollViewer_Drop;
}


void scrollViewer_PreviewDragEnter(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(DataFormats.FileDrop))
    {
        e.Effects = DragDropEffects.Copy;
    }
    else
    {
        e.Effects = DragDropEffects.None;
    }
}

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

bool IsDataAvailable = false;
void scrollViewer_Drop(object sender, DragEventArgs e)
{
    // Get data object
    var dataObject = e.Data as DataObject;

    // Check for file list
    if (dataObject.ContainsFileDropList())
    {
        // Process file names
        StringCollection fileNames = dataObject.GetFileDropList();
        bool isIsDataAvailable = false;
        try
        {
            var uri = new Uri(fileNames[0]);
            BitmapSource imageSource = new BitmapImage(uri);
            isIsDataAvailable = true;
        }
        catch (Exception error)
        {
            string errorMessage = error.ToString();
        }
        finally
        {
            IsDataAvailable = isIsDataAvailable;
        }
    }
}

My program just loads a dropped file from the explorer file list I drop on the ScrollViewer . The scbb.AllowDrop=true in the ScrollViewer has to be set. And the routines to handle basic drag and drop. Your code should work once the ScrollViewer allows dropping.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM