我正在寻找一种相对“简单”的方式来将ListBox用作WPF中的拖动源。我不想在后面的代码中启动拖动操作。 ListBox将成为自定义UserControl的一部分,该用户控件承载有关项目列表的功能。现在,它直接托管在MainWindow中。我对编程非常陌生。我认为我掌握了非常基本的知识。我有一个实现INotifyPropertyChanged的ViewModel,并且有一个定义并提供要显示的数据的模型。我做了一些测试,我想我知道如何在后面的代码中启动拖动操作,创建数据对象并用必要的信息“填充”它。
我读了很多东西。但是,我读得越多,我就越意识到,我似乎错过了MVVM的全部内容。
我非常感谢您提供任何帮助。在了解发生了什么之前,我不想使用框架或其他库。我知道那里有很多东西,但是也许你们可以朝着正确的方向推动我。非常感谢。
答案 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;
}
这是用户界面的一部分。树状视图中的某些条目具有较低的不透明度,因为它们已在场景中部署在地图上。埃德温·玛奇少将不在地图上。妓女是。