Answered by:
ListView Drop event not firing

Question
-
Hello all,
I have a ListView defined as such:
<ListView x:Name="videoListView" Grid.Row="1" CanDragItems="True" CanReorderItems="True" AllowDrop="True" IsEnabled="True" Margin="36,0,0,0" SelectionMode="Single"/>
...that contains a collection of Image controls. I can drag them around and when I drop them they reorder properly in the UI, but no Drop event ever fires. The goal is simply to catch when the user rearranges the controls in the ListView and then rearrange an internal data structure to match, am I going about this the wrong way?
EDIT:
Worked around the first problem by using (abusing?) the Image.Tag attribute to store my metadata, thus avoiding the need for the structure that needed updating in the first place. I still don't understand why the event fails to fire, though.
- Edited by Matthew Saunier Thursday, March 15, 2012 3:37 PM Second thread started for other issue
Tuesday, March 6, 2012 3:56 AM
Answers
-
EDIT:
Worked around the first problem by using (abusing?) the Image.Tag attribute to store my metadata, thus avoiding the need for the structure that needed updating in the first place. I still don't understand why the event fails to fire, though.
That's an ingenious solution, but I'm not looking forward to finding some ingenious workaround for every ordered list I want to display in a ListView. Out of curiosity, did you try explicitly setting two-way binding? (I'm not optimistic, but it would be cool if that worked.) What about using the HandledEventsToo flag on the AddHandler method?
Rebecca M. Riordan
- Marked as answer by Matthew Saunier Thursday, March 15, 2012 3:43 PM
Friday, March 9, 2012 2:25 PM -
Rebecca, thank you for the hint! This code does work:
DragEventHandler OnDropEvent = new DragEventHandler(OnDropHandler); public MainPage() { this.InitializeComponent(); videoListView.AddHandler(Control.DropEvent, OnDropEvent, true); } private static void OnDropHandler(object sender, DragEventArgs e) { //do stuff }
It still seems very broken that subscribing to ListView.Drop apparently does nothing, but this is a beta, so hopefully that will change.
No matter where you go, there you are. -Buckaroo Banzai
- Marked as answer by Matthew Saunier Friday, March 9, 2012 5:57 PM
- Edited by Matthew Saunier Thursday, March 15, 2012 3:35 PM
Friday, March 9, 2012 5:56 PM
All replies
-
Hi Matthew,
I suspect the first is because the ListView is handling the UIElement's Drop event itself as part of its reordering.
The second sounds like a bug. Without having debugged it, my guess is that the indices are getting thrown off by the removals. If you remove the items from last to first do you get more better results?
--Rob
Tuesday, March 6, 2012 11:14 PMModerator -
Hello Rob,
ListView is insensitive to the removal order, it glitches either way.
As regards the Drop event, I'm not seeing a way to manipulate ListView.base in any way from code; is there a way to change this behavior? Even though I've hacked my way around not having it, it could definitely make my life easier and my UI more responsive.
No matter where you go, there you are. -Buckaroo Banzai
- Proposed as answer by Rebecca M. Riordan Friday, March 9, 2012 2:10 PM
Wednesday, March 7, 2012 7:40 AM -
For the second issue can you provide a repro with more source? I believe what is happening is that as you remove the item the selected collection gets changes causing problems in the foreach.
For the first item you would need to derive from ListView and override OnDrop to get the drop notification before the ListView handles it.
-mark
Program Manager
MicrosoftThursday, March 8, 2012 7:52 PM -
Certainly, here is a copy of my project; let me know when I can take it down. I will look into overriding OnDrop; I did try making ListView's backing store an ObservableCollection, but that broke the animations and threw some very nasty exceptions, so I assume that that's a Bad Idea.
No matter where you go, there you are. -Buckaroo Banzai
- Edited by Matthew Saunier Thursday, March 8, 2012 8:52 PM
Thursday, March 8, 2012 8:50 PM -
I get a very strange error if I bind ListView to an ObservableCollection and try to add an item:
ObservableCollection<object> videoListCollection = new ObservableCollection<object>();
public MainPage()
{
this.InitializeComponent();
videoPlayer.MediaFailed += MediaFailed;
videoListView.ItemsSource = videoListCollection;
videoListCollection.CollectionChanged += videoListCollection_CollectionChanged;
}...then videoListView.Add(someObject);
System.Exception was unhandled by user code
HResult=-2147418113
Message=Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
Source=mscorlib
StackTrace:
at System.Runtime.InteropServices.WindowsRuntime.IVector`1.Append(T value)
at System.Runtime.InteropServices.WindowsRuntime.VectorToCollectionAdapter.Add[T](T item)
at Phorcys.MainPage.<plusButton_Click>d__0.MoveNext() in c:\Users\Matt\Documents\Visual Studio 11\Projects\Phorcys\Phorcys\MainPage.xaml.cs:line 86
InnerException:
Catastrophic failure and mscorlib is involved? Even if my code is bad, should this ever happen?
No matter where you go, there you are. -Buckaroo Banzai
Friday, March 9, 2012 7:21 AM -
EDIT:
Worked around the first problem by using (abusing?) the Image.Tag attribute to store my metadata, thus avoiding the need for the structure that needed updating in the first place. I still don't understand why the event fails to fire, though.
That's an ingenious solution, but I'm not looking forward to finding some ingenious workaround for every ordered list I want to display in a ListView. Out of curiosity, did you try explicitly setting two-way binding? (I'm not optimistic, but it would be cool if that worked.) What about using the HandledEventsToo flag on the AddHandler method?
Rebecca M. Riordan
- Marked as answer by Matthew Saunier Thursday, March 15, 2012 3:43 PM
Friday, March 9, 2012 2:25 PM -
Rebecca, thank you for the hint! This code does work:
DragEventHandler OnDropEvent = new DragEventHandler(OnDropHandler); public MainPage() { this.InitializeComponent(); videoListView.AddHandler(Control.DropEvent, OnDropEvent, true); } private static void OnDropHandler(object sender, DragEventArgs e) { //do stuff }
It still seems very broken that subscribing to ListView.Drop apparently does nothing, but this is a beta, so hopefully that will change.
No matter where you go, there you are. -Buckaroo Banzai
- Marked as answer by Matthew Saunier Friday, March 9, 2012 5:57 PM
- Edited by Matthew Saunier Thursday, March 15, 2012 3:35 PM
Friday, March 9, 2012 5:56 PM -
Glad that helped. It's expected behavior, though, with RoutedEvents. ButtonBase does the same thing with the Tap event that it "eats" to generate Click.
Rebecca M. Riordan
Friday, March 9, 2012 7:39 PM -
While maybe not helpful at first, the reason you do not receive the Drop event is that the ListView/GridView itself handles the Drop event. This was a conscious choice to handle the event during reorder since the ListView/GridView is actually handling the event to perform the reorder. Use the two methods mentioned in this thread (override OnDrop method or use AddHandler to get handled events) is the correct approach.
Also to mention - you can listen to the DragItemsStarting event on ListView/GridView to know when a reorder/drag is starting. In that event args you will get the list of items being dragged.
In addition the issues about reordering when databound to an ObservableCollection is all fixed now. Sorry for the problems.Hope this helps,
-markProgram Manager
Microsoft
This post is provided "as-is"Thursday, May 3, 2012 12:59 AM -
Is the issue of "reordering when databound to an ObservableCollection" all fixed? I am still seeing the same problem even when I set the binding as TwoWay.
abhi
Friday, July 6, 2012 5:46 PM