AllowDrop property not working for ToolStripItems
-
01-03-2021 - |
Question
I have successfully created DragDrop functionality with user controls. Now I am trying to allow DragDrop functionality on some components such as ToolStripButton.
The base class, ToolStripItem, supports AllowDrop and the DragEnter/DragDrop events...
ToolStripButton hides these properties in the designer, but they are publicly accessable.
Originally I tried doing the following for each ToolStripButton:
button.AllowDrop = true;
button.DragEnter += new DragEventHandler(button_DragEnter);
button.DragDrop += new DragEventHandler(button_DragDrop);
However, the events were not ever firing. These buttons are contained within a MenuStrip, so I changed the MenuStrip.AllowDrop to true. Then I started getting DragEnter and DragDrop events, but the DragDrop event would fail due to a threading/invoke problem when accessing the Tag property of the ToolStripItem.
The ToolStripItems cannot be invoked upon. So I have tried invoking their container, the MenuStrip, with the same function. I am still getting a threading/invoke problem where the thread stops running as soon as I try to access the ToolStripItem.
Here is the code I'm using to retrieve the Tag information after invoke:
void button_DragDrop(object sender, DragEventArgs e)
{
menuStrip.Invoke(new DragEventHandler(MyDragFunction), new object[] { sender, e });
}
void MyDragFunction(object sender, DragEventArgs e)
{
int id = (int)((ToolStripButton)sender).Tag;
// Debugging never reaches this line
int dragId = (int)e.Data.GetData(DataFormatName, false);
MoveItem(id, dragId);
}
Is Drag and Drop to a component like a ToolStripItem simply not possible? Or am I doing something wrong?
Solution
Here is the code I got to work for me.
I assign the DragDrop properties in the form constructor since they are hidden in the designer.
foreach (object o in menuStrip.Items)
{
if (o is ToolStripButton)
{
ToolStripItem item = (ToolStripItem)o;
item.AllowDrop = true;
item.DragEnter += new DragEventHandler(item_DragEnter);
item.DragOver += new DragEventHandler(item_DragOver);
item.DragDrop += new DragEventHandler(item_DragDrop);
}
}
private void item_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormatName, false))
{
e.Effect = DragDropEffects.Move;
}
}
private void item_DragOver(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormatName, false))
{
e.Effect = DragDropEffects.Move;
}
}
private void item_DragDrop(object sender, DragEventArgs e)
{
int id = (int)e.Data.GetData(DataFormatName, false);
int category = Convert.ToInt32((sender as ToolStripButton).Tag);
MyFunction(category, id);
}