onDragDrop behavior

In our application, we have subclassed from GoView and then subsequently overriden the “OnDragDrop” event logic as follows:

====================================================
protected override void OnDragDrop(DragEventArgs evt)<?:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

{

// Warn the user if a copy is about to take place.

//

if (evt.Effect.Equals(DragDropEffects.Copy) && evt.Data.GetDataPresent("Northwoods.Go.GoSelection"))

{

DialogResult dr = MessageBox.Show("You are about to COPY. Is this OK?",

"Confirm Selection Copy",

MessageBoxButtons.YesNo,

MessageBoxIcon.Question);

if (dr.Equals(DialogResult.No))

{

return; // Abandon the DragDrop operation

}

}

base.OnDragDrop(evt);

}

====================================================
The intent was to provide a warning when the use holds down the control key and drags (results in drag effect being set to copy) so that copy operations were an explicit decision on the part of the user. The warning is provided via the MessageBox.Show .
Here's the question/problem: After executing the MessageBox.Show and the subsequently calling base.OnDragDrop(evt), the "copy" seems to become a "move". If I comment out the MessageBox.Show, it works using the default behavior (ctrl-drag-drop = copy, drag-drop=move).
I'm sure I must be doing something fundamentally wrong, but can't figure it out. Any ideas? Thanks.

I'm not sure, but I suspect that just returning isn't the right thing to do. I would call GoView.DoCancelMouse() before returning.
Not necessarily related to your problem: did you want to have that code run when users do an external drag-and-drop into your GoView?
If not, I suggest you override GoView.DoInternalDrop instead, since that will be called only for drag-and-drops that start and end with that GoView.
>> I'm not sure, but I suspect that just returning isn't the right thing to
>> do. I would call GoView.DoCancelMouse() before returning.
Good point. The problem (probably my misunderstanding) occurs when I drop through the conditional logic without hitting the return. It should be a copy as far as I understand, but it is behaving like a move?
>> Not necessarily related to your problem: did you want to have that
>> code run when users do an external drag-and-drop into your GoView?
>> If not, I suggest you override GoView.DoInternalDrop instead, since
>> that will be called only for drag-and-drops that start and end with that
>> GoView.
Thank you. That's exactly the behavior I want. I didn't realize that I was able to segment between external and internal.

I checked, and your code seems to work when it’s in an override of GoView.DoInternalDrop instead of Control.OnDragDrop.

It also works in an override of GoView.DoExternalDrop.
Nevertheless, I would still call GoView.DoCancelMouse when aborting the drop.

I did exactly as you recommended. I overrode both DoInternalDrop and DoExternalDrop. In addition, I implemented the DoMouseCancel prior to the return. Using the same logic from above with a small change for the base.xxx call, it worked flawlessly.

For some reason, the OnDragDrop behaved differently when a MessageBox was shown (see above, treated a copy operation like a move). Any insights would be great.
Thanks again for the extremely responsive and accurate support.
John Cook.

Control.OnDragDrop is the general drop handling/raising method for all Controls. But you can’t modify the behavior of existing event handlers by overriding this method. (Well, you could skip all event handlers by not calling the base method, I suppose, but that would be highly questionable behavior. The Microsoft documentation repeatedly reminds everyone to be sure to call the base method whenever overriding an On… method that raises events.)

The predefined behavior includes the (external) one that GoView defines for accepting drops from other GoViews and the (internal) one that GoView/GoToolDragging implements for accepting move or copy drags within a view.
In the case of an internal drag-and-drop, the GoToolDragging tool is running. By the time the user is done clicking on the MessageBox buttons, the mouse is no longer in the same state as it had been. Its position is different, its buttons are no longer pressed, and its modifiers may be different. So of course the tool might not be able to behave in the expected manner. If you were implementing similar drag-and-drop functionality without any use of GoDiagram, you might have had the same problem unless you saved the mouse state before bringing up the MessageBox.

Walter,

I cannot seem to get an external drag and drop to work.
I can get "drag" to work. I have an EventHandler for the DragDrop Event that is supposed to handle all of the "dropping". However, the data being passed in is constantly null.
void PedigreeTreeUserControl_DragDrop(object sender, DragEventArgs evt) { IDataObject data = evt.Data; Point screenPnt = new Point(evt.X, evt.Y); Point viewPnt = PointToClient(screenPnt);

PointF docPnt = myView.ConvertViewToDoc(viewPnt);
PersonNode node = null;
GoObject gO = null;
gO = myView.PickObject(true, false, docPnt, true);
if (data.GetDataPresent(DataFormats.Serializable)) {
evt.Effect = DragDropEffects.All;
}
else {
evt.Effect = DragDropEffects.None;
}
if (gO != null)
{
node = myView.PickObject(true, false, docPnt, true).TopLevelObject as PersonNode;
}
if (node != null)
{
Object oDraggedData = data.GetData(DataFormats.Serializable);
if (oDraggedData != null && oDraggedData.GetType() == typeof(ListViewItem))
{
ListViewItem lvi = (ListViewItem)oDraggedData;
}
}
}

Any ideas as to why the data is not being passed in? I am dragging the data from another WinForms control that is pretty much a glorified GridView control.

You shouldn’t be using DataFormats.Serializable. I don’t know what data type you are using in your GridView for the data, but perhaps DataFormats.StringFormat or typeof(String).

Even without using DataFormats.Serializable I can’t get the data. Every time I step through the debugger and check for a value I get null.

I am using a 3rd party component from DevExpress.
Here is their sample code which works (obviously they are not performing a drag-drop operation onto any goDiagram controls).
private DevExpress.XtraTreeList.Nodes.TreeListNode GetDragNode(IDataObject data) { return data.GetData(typeof(DevExpress.XtraTreeList.Nodes.TreeListNode)) as DevExpress.XtraTreeList.Nodes.TreeListNode; } private string GetStringByNode(DevExpress.XtraTreeList.Nodes.TreeListNode node) { string ret = ""; for (int i = 0; i < treeList1.Columns.Count; i++) ret += node.GetDisplayText(i) + (i < treeList1.Columns.Count - 1 ? "; " : "."); return ret; } private void listBox1_DragEnter(object sender, System.Windows.Forms.DragEventArgs e) { if (GetDragNode(e.Data) != null) e.Effect = DragDropEffects.Copy; } private void listBox1_DragDrop(object sender, System.Windows.Forms.DragEventArgs e) { DevExpress.XtraEditors.ListBoxControl lb = sender as DevExpress.XtraEditors.ListBoxControl; DevExpress.XtraTreeList.Nodes.TreeListNode node = GetDragNode(e.Data); if (node != null) { string dragString = GetStringByNode(node); int ind = lb.IndexFromPoint(lb.PointToClient(new Point(e.X, e.Y))); if (ind == -1) lb.Items.Add(dragString); else lb.Items.Insert(ind, dragString); } }
Even before executing the OnDragDrop code I can see that data is returning null (not in the code above but in my code which is identical except for the fact that I am dragging onto a GoView) b/c I have a breakpoint in my OnDragEnterCode which checks evt.Data != null.
Any suggestions?

So you are looking for typeof(TreeListNode) as the data format, right?

I just realized what my issue was with that last piece of code.

The sample was using a TreeList as the "sender". Also, I was implementing the DragDrop event handler outside of my node class. I could simply move everything to my node class where I already "know" what node I've clicked (as well as the data coming into the event handler) and just process everything there.
Only 1 problem remains: There doesn't seem to be an event for OnDragDrop for the node!!!