Written in front: This article is improvised, so there are inevitably omissions and lied place. Here, you are expected to provide comments and share your thoughts and suggestions.
This is a short article that describes how to implement drag-and-drop functionality in WPF.
The first thing to be clear to the reader is: drag and drop is mainly divided into drag-and-drop source and drag-and-drop target of two components. Drag-and-drop sources and drop targets each have different events. Software developers need to perform the appropriate functions in the appropriate event.
Imagine the drag and drop is how to operate: The user selected an interface element, and the left mouse button to move the mouse, and finally, the drag and drop target release the left mouse button to complete the data drag and drop the whole process. From the point of view of program writing, the user needs to move to start drag-and-drop by left-clicking the item and pressing it, giving the appearance feedback of the current drag-and-drop state during mouse movement, and attempting to add the item to the target when the mouse is released.
For any software interface, the left mouse button press and move behavior does not necessarily lead to the start of drag and drop. As a result, software developers need to write their own code to initiate drag-and-drop functionality rather than being decided by WPF. This is why software developers need to invoke Dragdrop.dodragdrop () themselves to initiate a drag-and-drop operation under certain conditions. The Dragdrop.dodragdrop () function accepts three parameters: DragSource, data, and allowedeffects. It is particularly important to note that the DragSource parameter. This parameter identifies the message source for the drag operation, and also determines who sent all the message source events. The parameter data is used to wrap the drag&drop. In general, it is an instance of a DataObject type. Within the instance, the data that is actually manipulated by the drag and drop should be wrapped. Finally, allowedeffects can be used to specify the effect of a drag-and-drop operation. The fragment that invokes the function can be as follows:
Dragdrop.dodragdrop (Mlistbox, DataObject, dragdropeffects.copy);
After the drag-and-drop operation is initiated, the software developer needs to deal with the sequence of events that occur during the drag-and-drop process. In this case, the software developer cannot expect to respond to the drag behavior by responding to events such as Mouse.mousemove. This is because the Dragdrop.dodragdrop () function is actually a blocking function. These events are not sent until the drag-and-drop behavior is terminated. Instead, software developers can use the drag-and-drop events provided by the source and target. The drag source provides events for QueryContinueDrag, GiveFeedback, and corresponding preview-events. The QueryContinueDrag event is used to determine whether to continue the drag-and-drop operation. This event occurs when the state of the keyboard or mouse button has changed. GiveFeedback is used to provide users with drag-and-drop feedback, such as the image of the dragged interface element changes with the mouse, or to provide a ToolTip to prompt the user's current drag-and-drop effect. The message is timed out during the drag process, so the software developer can also use it as a timer event. In this case, it is important to understand the timing of each drag-and-drop event because software developers cannot use other events during the drag-and-drop process.
Also, when you see the preview-event, I'm sure you can think of this as a tunneling/bubbling routed event. Therefore, the handling of these events does not necessarily require adding event handlers to the drop source, but can be overridden in a higher level, such as rewriting the window's Ongivefeedback () function. The advantage of this is that it provides a more centralized drag-and-drop logic and has a better semantic feature when it comes to changing higher-level interface elements, such as the state Bar state of a window. The disadvantage of doing so is that it does not fit well with multiple drag sources in the window. Of course, it is also a good choice to listen to messages from the source at a high level.
If we need to implement the feature of the drag-and-drop interface element as a preview in the drag-and-drop process, the implementation of this feature is as follows:
Mlistbox.previewmousemove + =Onpreviewlistboxmousemove;mlistbox.querycontinuedrag+=Onquerycontinuedrag;Private voidOnquerycontinuedrag (Objectsender, QueryContinueDragEventArgs e) {madornerlayer.update (); ...}Private voidOnpreviewlistboxmousemove (Objectsender, MouseEventArgs e) {ListBoxItem ListBoxItem= ...//Find your actual visual want to drag..... Dragdropadorner Adorner=NewDragdropadorner (ListBoxItem); Madornerlayer=Adornerlayer.getadornerlayer (Mtoplevelgrid); Madornerlayer.add (adorner); DataItem DataItem= Listboxitem.content asDataItem; DataObject DataObject=NewDataObject (Dataitem.clone ()); //Here , we should notice that DragSource param would specify on which//Control the Drag&drop event would be firedSystem.Windows.DragDrop.DoDragDrop (Mlistbox, DataObject, dragdropeffects.copy);
Where Dragdropadorner is used to display a preview of the dragged interface element. It uses the adorner. If the reader is interested in the implementation of the control, please download the sample program to view it yourself. With regard to the use of adorner, I will write a special article when I have time.
The next step is to drag and drop the target event. The drag target sends DragEnter, DragOver, DragLeave, drop, and the corresponding preview-event. The significance of these events is clear, and I believe you can tell from your name the timing of these events. What you need to be aware of in these events is the incoming DragEventArgs. By setting its effects members, the software developer can control the state of the mouse to prompt the user for the cursor feedback of the current drag action. At the same time, through its Data property, the software developer can get the data passed in when the DoDragDrop () function is called.
Here is the code that responds to the drag-and-drop target event:
Private voidOnDragOver (Objectsender, DragEventArgs e) {e.effects=DragDropEffects.None; //Find The corresponding TreeView item in Mtreeview and select itPoint pos =e.getposition (Mtreeview); Hittestresult result=visualtreehelper.hittest (Mtreeview, POS); if(Result = =NULL) return; TreeViewItem SelectedItem= utils.findvisualparent<treeviewitem>(result.) Visualhit); if(SelectedItem! =NULL) selecteditem.isselected=true; E.effects=dragdropeffects.copy;}Private voidOnDrop (Objectsender, DragEventArgs e) { //Drop the data item into corresponding TreeView itemPoint pos =e.getposition (Mtreeview); Hittestresult result=visualtreehelper.hittest (Mtreeview, POS); if(Result = =NULL) return; TreeViewItem SelectedItem= utils.findvisualparent<treeviewitem>(result.) Visualhit); if(SelectedItem = =NULL) return; DataItem Parent= Selecteditem.header asDataItem; DataItem DataItem= e.Data.GetData (typeof(DataItem)) asDataItem; if(Parent! =NULL&& DataItem! =NULL) parent. Items.Add (DataItem);}
The reader's attention is the call to the GetData () function in the code. In the Drag&drop process, if you want to get data from DataObject, you must use the original type. If a is a base class for B, and an instance of type B is sealed in DataObject, then the software developer needs to use typeof (B) in Dataobject.getdata () instead of typeof (A).
Software developers need to be aware of a range of issues when implementing drag-and-drop functionality.
The first is dragdropeffect. Each value in the enumeration corresponds to a specific behavior of the drag-and-drop process. These skins have a specific idiom in UI design and user use. So in the development process to think about what you want to do with the drag target, to prevent users in the use of the process to create confusion.
In addition, the external drag-and-drop source is a common drag-and-drop feature, such as dragging files into the application for loading. In some cases, dragging a target event does not provide the required information. The IDataObject interface provides only the GetData () function when dragging multiple files into the application. In this case, the software developer can attempt to convert it to an instance of the DataObject type and return all dragged files through the getfiledroplist () function.
It is also important to note that the mouse position is obtained. During the drag-and-drop process, the position of the mouse cannot be obtained through the WPF standard methods such as the mouse class. In some cases, the method will return an incorrect location. This is because during the drag-and-drop process, the control of the mouse is managed by the drag source. This management process uses the WIN32 function, which makes WPF unable to correctly return the location information for the mouse. A workaround is to use PInvoke to invoke the Win32 API GetCursorPos ().
Another small trick to mention is how to disable drag and drop. Standard controls include controls that, by default, can be used as a drag target, such as a TextBox. To disable this feature, software developers can set the handled property of DragEventArgs in Onpreviewdragenter () and Onpreviewdragover () overloads to True, and set the effects to none, To simulate the effect of no drag and drop.
SOURCE Download: http://download.csdn.net/detail/silverfox715/3884722
Reprint please specify the original address: http://www.cnblogs.com/loveis715/archive/2011/12/05/2277384.html
Commercial reprint please contact me in advance:[email protected]
WPF drag-and-drop functionality for ZZ