Drag and Drop in a ListView

T

Tom Bean

I wrote an C# application that uses drag and drop to copy the contents of
one ListViewItem to another. I call DoDragDrop() in the ItemDrag event
handler, however, the ItemDrag event is being fired when an item in the
ListView is clicked to select it instead of being fired when the item is
dragged.

This is causing a problem when users click on an item and move the moue
(after the mouse button has been released) because the app tries to perform
the drag and drop operation, copy, even though the item wasn't dragged to
another item before the mouse button was released.

I have tried implementing handlers for the MouseUpand QueryContinueDrag
events to cancel the drag and drop if the mouse button is released over the
selected item. Neither event handler is hit before the mouse is moved off
the selected item.

I need to find a way to cancel the drag or even better to find out how to
prevent ItemDrag from firing when the ListViewitem is clicked on to select
it.

Has anyone got any suggestions about how to solve this problem?

Thanks,
Tom
 
L

Linda Liu[MSFT]

Hi Tom,

I performed a test based on your description, but didn't reproduce the
problem. In my test, the ItemDrag event of the ListView isn't fired when I
select one item by clicking it. Only when I click down the mouse on an
ListViewItem and move, the ItemDrag event is fired.

The following is the walkthough of my test.
1. Create a WinForm application project.
2. Add a ListView on the Form1 and add some items into the ListView.
3. Set the AllowDrop property of the ListView to true and handle the
ItemDrag, ItemEnter and ItemDrop events of the ListView. The following is
the code in the Form1.

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.listView1.AllowDrop = true;
this.listView1.ItemDrag += new
ItemDragEventHandler(listView1_ItemDrag);
this.listView1.DragEnter += new
DragEventHandler(listView1_DragEnter);
this.listView1.DragDrop += new
DragEventHandler(listView1_DragDrop);
}
void listView1_DragDrop(object sender, DragEventArgs e)
{
ListViewItem item = e.Data.GetData(typeof(ListViewItem)) as
ListViewItem;
if (item != null)
{
Point pt = this.listView1.PointToClient(new Point(e.X,
e.Y));
ListViewItem hoveritem = this.listView1.GetItemAt(pt.X,
pt.Y);
if (hoveritem != null)
{
hoveritem.Text = item.Text;
}
}
}

void listView1_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(ListViewItem)))
{
e.Effect = DragDropEffects.Copy;
}
}
void listView1_ItemDrag(object sender, ItemDragEventArgs e)
{
this.listView1.DoDragDrop(this.listView1.SelectedItems[0],
DragDropEffects.All);
}
}

If the problem is still not solved, could you please send me a sample
project that could just reproduce the problem? To get my actual email
address, remove 'online' from my displayed email address.

Sincerely,
Linda Liu
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
T

Tom Bean

Linda,

I think I found my problem. Over time more functionality has been added to
a method called in the SelectedIndexChanged event handler for the ListView.
I believe the amount of time taken to perform all the operations in this
method has disrupted the normal flow of events. In other words, the
ItemDrag event is fired before exiting the SelectedIndexChanged event
handler.

I am thinking about calling the method in the SelectedIndexChanged event
handler using MethodInvoker so SelectedIndexChanged exits sooner. Do you
think this will solve the problem or do you have any other suggestions?

Thanks,
Tom

Linda Liu said:
Hi Tom,

I performed a test based on your description, but didn't reproduce the
problem. In my test, the ItemDrag event of the ListView isn't fired when I
select one item by clicking it. Only when I click down the mouse on an
ListViewItem and move, the ItemDrag event is fired.

The following is the walkthough of my test.
1. Create a WinForm application project.
2. Add a ListView on the Form1 and add some items into the ListView.
3. Set the AllowDrop property of the ListView to true and handle the
ItemDrag, ItemEnter and ItemDrop events of the ListView. The following is
the code in the Form1.

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.listView1.AllowDrop = true;
this.listView1.ItemDrag += new
ItemDragEventHandler(listView1_ItemDrag);
this.listView1.DragEnter += new
DragEventHandler(listView1_DragEnter);
this.listView1.DragDrop += new
DragEventHandler(listView1_DragDrop);
}
void listView1_DragDrop(object sender, DragEventArgs e)
{
ListViewItem item = e.Data.GetData(typeof(ListViewItem)) as
ListViewItem;
if (item != null)
{
Point pt = this.listView1.PointToClient(new Point(e.X,
e.Y));
ListViewItem hoveritem = this.listView1.GetItemAt(pt.X,
pt.Y);
if (hoveritem != null)
{
hoveritem.Text = item.Text;
}
}
}

void listView1_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(ListViewItem)))
{
e.Effect = DragDropEffects.Copy;
}
}
void listView1_ItemDrag(object sender, ItemDragEventArgs e)
{
this.listView1.DoDragDrop(this.listView1.SelectedItems[0],
DragDropEffects.All);
}
}

If the problem is still not solved, could you please send me a sample
project that could just reproduce the problem? To get my actual email
address, remove 'online' from my displayed email address.

Sincerely,
Linda Liu
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no
rights.
 
L

Linda Liu[MSFT]

Hi Tom,

Thank you for your prompt reply!

I performed a test on your new finding. I add some lines of code which will
take several seconds to complete in the SelectedIndexChanged event handler
as follows:

void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
Console.WriteLine("begin: selected index changed");
int j = 0;
for (int i = 0; i < 10000; i++)
{
for (int k = 0; k < 10000; k++)
{
j += i;
}
}
Console.WriteLine("end: selected index changed");
}

void listView1_ItemDrag(object sender, ItemDragEventArgs e)
{
Console.WriteLine("item drag");
}

Then I run my test application by pressing F5 and select and drag one item
in the ListView. The result I get is that the string "item drag" is always
printed after the string "end: selected index changed" in the Output
window, which means the ItemDrag event handler is called only after the
SelectedIndexChanged event handler is completed.

If you don't call the time-consuming method from within the
SelectedIndexChanged event handler, does the problem disappear? If so, you
may have a try calling the Control.BeginInvoke method to execute a delegate
for the time-consuming method asynchronously.

Hope this helps.
If the problem is still not solved, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
 
T

Tom Bean

Linda,

I don't think your loop from 0 to 100,000,000 consumes nearly as much time
as reading a lot of data from SQL Server and populating over 300 controls
and setting the background color of 100 of them. I know the ItemDrag,
DragEnter and DragDrop events are being fired inside the SelectIndexChanged
event handler because of various breakpoints I set.

I got concerned about trying to populate the controls in a BeginInvoke()
call so I resolved the problem by disabling the ItemDrag event handler while
in the SelectedIndexChanged event handler. Now I'm assured the ItemDrag
event handler is not called while the app is busy loading the data.

Thanks,
Tom
 
L

Linda Liu[MSFT]

Hi Tom,

Thank you for your prompt reply!

Is the problem solved now? If not, please feel free to let me know.

Thank you for using our MSDN Managed Newsgroup Support Service!

Sincerely,
Linda Liu
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top