拖动源列表框

时间:2019-05-25 11:06:03

标签: c# wpf mvvm

我正在寻找一种相对“简单”的方式来将ListBox用作WPF中的拖动源。我不想在后面的代码中启动拖动操作。 ListBox将成为自定义UserControl的一部分,该用户控件承载有关项目列表的功能。现在,它直接托管在MainWindow中。我对编程非常陌生。我认为我掌握了非常基本的知识。我有一个实现INotifyPropertyChanged的ViewModel,并且有一个定义并提供要显示的数据的模型。我做了一些测试,我想我知道如何在后面的代码中启动拖动操作,创建数据对象并用必要的信息“填充”它。

我读了很多东西。但是,我读得越多,我就越意识到,我似乎错过了MVVM的全部内容。

我非常感谢您提供任何帮助。在了解发生了什么之前,我不想使用框架或其他库。我知道那里有很多东西,但是也许你们可以朝着正确的方向推动我。非常感谢。

1 个答案:

答案 0 :(得分:0)

让我们快速浏览一下您将用于拖放和大致操作的事件。

用户将在项目上按住鼠标左键。您要为此获取数据。

这种点击并保持无法神奇地识别出来。您需要对此代码进行四舍五入,并允许用户单击或单击微小的拖动,然后单击鼠标向上。

以某种方式确定用户要拖动的内容,并获得他要拖动的数据。

光标移动。

在某些时候,用户可以通过鼠标悬停在其他控件上。 然后,您可以对开始存储时隐藏的数据进行处理。

这里是一种解释:

https://www.c-sharpcorner.com/uploadfile/dpatra/drag-and-drop-item-in-listbox-in-wpf/

看看他在哪里使用ItemFromContainer的东西?

讨厌吧?

对于MVVM,要拖动的listboxitem具有数据上下文。将其转换为该行viewmodel的任何内容,即可获得数据。

优雅得多。

比使用列表框更好地使用列表框。

到目前为止清楚吗?

好的,这是完整应用程序中的一些难点。这是将树视图中的项目拖到画布上。树视图左侧到地图右侧的一个单位(部分)。由于画布不会被裁剪,因此该作品被添加到画布中,因此您可以看到它被拖动了,但它开始于树状视图和画布之外。

树视图和画布都在网格中,其中一些事件与之关联。

每个部件都有一个ViewModel PieceVM,该模型具有X Y属性定义位置。

    Point lastDragPosition = new Point(0,0);
    private PieceVM pieceBeingDragged = null;

    private void grid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        lastDragPosition = new Point(0, 0);
        if ( !( e.OriginalSource is FrameworkElement))
            return;
        if(! (( (FrameworkElement)e.OriginalSource).DataContext is  PieceVM))
            return;
        pieceBeingDragged = ((FrameworkElement)e.OriginalSource).DataContext as PieceVM;
        if (pieceBeingDragged?.IsOnBoard !=true)
        {
            return;
        }
        // Piece is on the board, check whether this is a treeviewitem
        if(TreeHelper.FindVisualParent<TreeViewItem>((DependencyObject)e.OriginalSource) != null)
        {
            pieceBeingDragged = null;
        }
    }

    private bool isSignificantDrag(Point was, Point now)
    {
        if (Math.Abs(now.X - was.X) > SystemParameters.MinimumHorizontalDragDistance ||
            Math.Abs(now.Y - was.Y) > SystemParameters.MinimumVerticalDragDistance)
            return true;
        return false;
    }

    private void grid_PreviewMouseMove(object sender, MouseEventArgs e)
    {
        if (System.Windows.Input.Mouse.LeftButton != MouseButtonState.Pressed)
        {
            return;
        }
        if (pieceBeingDragged == null)
        {
            return;
        }
        Point pt = e.GetPosition(MainCanvas);
        bool isDragging = (bool)this.GetValue(MainWindow.IsDraggingPieceProperty);
        if (isDragging)
        {
            MoveDraggedPiece(pt);
            return;
        }
        if (lastDragPosition.X == 0 || lastDragPosition.Y == 0)
        {
            lastDragPosition = pt;
            return;
        }
        if(pt.X < 0 && !isSignificantDrag(pt, lastDragPosition))
        {
            lastDragPosition = pt;
            return;
        }
        StartPieceDrag(pt);
    }

    private void StartPieceDrag(Point pt)
    {
        if (pieceBeingDragged == null)
        {
            return;
        }
        this.SetCurrentValue(MainWindow.IsDraggingPieceProperty, true);
        MoveDraggedPiece(pt);
        if(!App.mvm.PiecesOnBoard.Contains(pieceBeingDragged))
        {
            App.mvm.PiecesOnBoard.Add(pieceBeingDragged);
            pieceBeingDragged.IsOnBoard = true;
        }

        Keyboard.ClearFocus();
        pieceBeingDragged.IsValidLocation = true;
    }

    private void MoveDraggedPiece(Point newLocation)
    {
        pieceBeingDragged.X = newLocation.X ;
        pieceBeingDragged.Y = newLocation.Y ;
    }
    private void grid_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        if (pieceBeingDragged == null)
            return;
        pieceBeingDragged.EvaluateLocation();
        lastDragPosition = new Point(0, 0);
        this.SetCurrentValue(MainWindow.IsDraggingPieceProperty, false);
        pieceBeingDragged = null;
    }

这是用户界面的一部分。树状视图中的某些条目具有较低的不透明度,因为它们已在场景中部署在地图上。埃德温·玛奇少将不在地图上。妓女是。

enter image description here