WPF:如何使用嵌套(分层)控件实现拖放

时间:2021-12-20 13:15:59

Using WPF I've succeeded at implementing drag and drop to rearrange items within a list(view or box) and also to drag and drop items between lists.

使用WPF我已成功实现拖放以重新排列列表(视图或框)中的项目,并在列表之间拖放项目。

Now I am trying figure out how to implement drag and drop with NESTED lists.

现在我正在尝试弄清楚如何使用NESTED列表实现拖放。

For instance I have a listview containing projects and each project item contains another listview of tasks. I want to be able to drag and drop to rearrange the order of projects and also to reorder tasks and move them between projects.

例如,我有一个包含项目的列表视图,每个项目项包含另一个任务列表视图。我希望能够拖放以重新排列项目的顺序,并重新排序任务并在项目之间移动它们。

I have code that successfully does one of the other, but I can't figure out how to do both.

我有成功完成另一个的代码,但我无法弄清楚如何做到这两点。

It seems like there is some sort of painful solution that would involve hit testing and maybe the z-order of the nested lists, but I can't find any examples of this.

似乎有某种痛苦的解决方案涉及命中测试,也许是嵌套列表的z顺序,但我找不到任何这样的例子。

Can anybody offer any pointers?

任何人都可以提供任何指示吗?

FYI: The working code that I currently have implemented is based on the following two excellent articles on WPF drag and drop:

仅供参考:我目前实施的工作代码基于以下两篇关于WPF拖放的优秀文章:

http://bea.stollnitz.com/blog/?p=53 http://www.codeproject.com/KB/WPF/ListViewDragDropManager.aspx

http://bea.stollnitz.com/blog/?p=53 http://www.codeproject.com/KB/WPF/ListViewDragDropManager.aspx

4 个解决方案

#1


4  

Since MouseMove and most others in wpf are routed events, you could just check e.OriginalSource in a common event handler. Then you can decide which element to drag based on which element the mouse was on, probably using one of those "find parent which satisfies condition" helper method techniques. Additionally, you can set e.Handled if you have several elements in the visual tree subscribing to the event.

由于MouseMove和wpf中的大多数其他路由事件,您可以在公共事件处理程序中检查e.OriginalSource。然后,您可以根据鼠标所在的元素决定拖动哪个元素,可能使用其中一个“查找满足条件的父级”辅助方法技术。此外,如果订阅事件的可视树中有多个元素,则可以设置e.Handled。

#2


2  

Just first thoughts is, why not use a TreeView instead of a ListView if you're going to have nesting?

首先想一想,如果你想要嵌套,为什么不使用TreeView而不是ListView?

#3


0  

AllowDrop must be true on any control.

任何控件上的AllowDrop都必须为true。

#4


0  

I went through a similar issue when working on an app with listboxes of nested user controls.
I handled all of this in the PreviewMouseButtonDown event on a per control level. I check the coordinates of the point that was clicked. If it came from anywhere in the parent ListBoxItem that was not in the ListBox, I process the the DragDrop.DoDragDrop() there. If it came from inside the ListBoxItem, I let it bubble down to the child ListBox's PreviewMouseButtonDown event. I check to see where the location is in the child ListBox to see which item was clicked on so I can grab it and do the DragDrop on this level instead.

在处理具有嵌套用户控件列表框的应用程序时,我遇到了类似的问题。我在每个控件级别的PreviewMouseButtonDown事件中处理了所有这些。我检查点击的点的坐标。如果它来自父ListBoxItem中不在ListBox中的任何地方,我在那里处理DragDrop.DoDragDrop()。如果它来自ListBoxItem内部,我让它向下冒泡到子ListBox的PreviewMouseButtonDown事件。我检查孩子ListBox中的位置,看看哪个项目被点击了所以我可以抓住它并在这个级别上执行DragDrop。

The pseudo-code is as follow:

伪代码如下:

Parent ListBox  
--  PListBoxItem1  
--  PListBoxItem2  
--  PListBoxItem3  
----    Child ListBox  
------  Child ListBoxItem1  
------  Child ListBoxItem2  -Click drag started here  
------  Child ListBoxItem3  

Code:

码:

Parent_List_Box_PreviewMouseButtonDown  
If mouse position is not inside the Child ListBox Then  
  DoDragDrop() on the Parent level with this ListBoxItem  
End If

Child_ListBox_PreviewMouseButtonDown  
Determine which item the mouse was clicked on relative to the Child ListBox  
DoDragDrop() on the Child level with this ListBoxItem  

So since the click was inside a Child's ListBox, the event bubbles down to the lowest handler that passes the criteria for the DragEvent.

因此,由于单击位于Child的ListBox内,因此事件会向下传递到传递DragEvent标准的最低处理程序。

Hope this helps!

希望这可以帮助!

#1


4  

Since MouseMove and most others in wpf are routed events, you could just check e.OriginalSource in a common event handler. Then you can decide which element to drag based on which element the mouse was on, probably using one of those "find parent which satisfies condition" helper method techniques. Additionally, you can set e.Handled if you have several elements in the visual tree subscribing to the event.

由于MouseMove和wpf中的大多数其他路由事件,您可以在公共事件处理程序中检查e.OriginalSource。然后,您可以根据鼠标所在的元素决定拖动哪个元素,可能使用其中一个“查找满足条件的父级”辅助方法技术。此外,如果订阅事件的可视树中有多个元素,则可以设置e.Handled。

#2


2  

Just first thoughts is, why not use a TreeView instead of a ListView if you're going to have nesting?

首先想一想,如果你想要嵌套,为什么不使用TreeView而不是ListView?

#3


0  

AllowDrop must be true on any control.

任何控件上的AllowDrop都必须为true。

#4


0  

I went through a similar issue when working on an app with listboxes of nested user controls.
I handled all of this in the PreviewMouseButtonDown event on a per control level. I check the coordinates of the point that was clicked. If it came from anywhere in the parent ListBoxItem that was not in the ListBox, I process the the DragDrop.DoDragDrop() there. If it came from inside the ListBoxItem, I let it bubble down to the child ListBox's PreviewMouseButtonDown event. I check to see where the location is in the child ListBox to see which item was clicked on so I can grab it and do the DragDrop on this level instead.

在处理具有嵌套用户控件列表框的应用程序时,我遇到了类似的问题。我在每个控件级别的PreviewMouseButtonDown事件中处理了所有这些。我检查点击的点的坐标。如果它来自父ListBoxItem中不在ListBox中的任何地方,我在那里处理DragDrop.DoDragDrop()。如果它来自ListBoxItem内部,我让它向下冒泡到子ListBox的PreviewMouseButtonDown事件。我检查孩子ListBox中的位置,看看哪个项目被点击了所以我可以抓住它并在这个级别上执行DragDrop。

The pseudo-code is as follow:

伪代码如下:

Parent ListBox  
--  PListBoxItem1  
--  PListBoxItem2  
--  PListBoxItem3  
----    Child ListBox  
------  Child ListBoxItem1  
------  Child ListBoxItem2  -Click drag started here  
------  Child ListBoxItem3  

Code:

码:

Parent_List_Box_PreviewMouseButtonDown  
If mouse position is not inside the Child ListBox Then  
  DoDragDrop() on the Parent level with this ListBoxItem  
End If

Child_ListBox_PreviewMouseButtonDown  
Determine which item the mouse was clicked on relative to the Child ListBox  
DoDragDrop() on the Child level with this ListBoxItem  

So since the click was inside a Child's ListBox, the event bubbles down to the lowest handler that passes the criteria for the DragEvent.

因此,由于单击位于Child的ListBox内,因此事件会向下传递到传递DragEvent标准的最低处理程序。

Hope this helps!

希望这可以帮助!