I am making my first Windows Store app in Visual Studios 2012. I have a gridview control that I have enabled to be reordered. I have code that I need to run when the list is reordered. I have tried the Drop event. It does not fire. I tried several other drag events, which also did not fire. It seems like this should be so simple... Thanks for your time!
-
1You can use `CollectionChanged` event of `ObservableCollection
`, if you have provided `ItemsSource` of `GridView` with `ObservableCollection – Farhan Ghumra May 06 '13 at 05:10`
1 Answers
You cannot reorder a GridView
unless the ItemsSource
is bound to an ObservableCollection
and CanReorderItems
, CanDragItems
, and AllowDrop
are set to true
. It is not necessary to use a CollectionViewSource
to enable reordering in your gridview
. In fact, a collectionviewsource
is often used for grouping a gridview
and reordering is not possible when data is grouped.
Anyway, your XAML would look like this:
<Grid Background="Black">
<Grid.DataContext>
<local:MyModel/>
</Grid.DataContext>
<GridView CanReorderItems="True" CanDragItems="True" AllowDrop="True"
ItemsSource="{Binding Items}">
</GridView>
</Grid>
Although any enumerable
can be bound to the ItemsSource
of a GridView
it is only an ObservableCollection
that enables reorder. Yes, you can use a custom type that implements reorder, but why mess with that when ObservableCollection
does it for you?
Your view model might look like this:
public class MyModel
{
public MyModel()
{
foreach (var item in Enumerable.Range(1, 50))
Items.Add(item);
Items.CollectionChanged += Items_CollectionChanged;
}
ObservableCollection<int> m_Items = new ObservableCollection<int>();
public ObservableCollection<int> Items { get { return m_Items; } }
object m_ReorderItem;
int m_ReorderIndexFrom;
void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Remove:
m_ReorderItem = e.OldItems[0];
m_ReorderIndexFrom = e.OldStartingIndex;
break;
case NotifyCollectionChangedAction.Add:
if (m_ReorderItem == null)
return;
var _ReorderIndexTo = e.NewStartingIndex;
HandleReorder(m_ReorderItem, m_ReorderIndexFrom, _ReorderIndexTo);
m_ReorderItem = null;
break;
}
}
void HandleReorder(object item, int indexFrom, int indexTo)
{
Debug.WriteLine("Reorder: {0}, From: {1}, To: {2}", item, indexFrom, indexTo);
}
}
In the code above, the reorder event
is not real. It is derived from a combination of the "Remove" action and the "Add" action in the CollectionChanged
event. Here's why this is awesome. If the reorder was only available from the GridView
then the ViewModel
would not be able to handle it. Because the underlying list is how you detect reorder, the ViewModel
is enabled.
Every case is slightly different. You may not care about the Index so you can simplify the code. You may not allow adding or removing from the collection so you only need to monitor the Add action. Again, it depends on your situation. My sample code above should get 99% of the cases taken care of.
Remember, GridView
is not the only control that allows reorder. Any control based on ListViewBase
(like the ListView
) supports reorder - still using ObservableCollection
. But GridView
is the most common control to use this feature. For sure.
Oh, to answer your question!
There is no event that indicates a reorder. Reorder is a derived action based on a combination of actions in the underlying ObservableCollection
CollectionChanged
event. Make sense?
By the way, here's sample syntax to bind to a CollectionViewSource
, if you choose to:
<Grid Background="Black">
<Grid.DataContext>
<local:MyModel/>
</Grid.DataContext>
<Grid.Resources>
<CollectionViewSource x:Name="CVS" Source="{Binding Items}" />
</Grid.Resources>
<GridView CanReorderItems="True" CanDragItems="True" AllowDrop="True"
ItemsSource="{Binding Source={StaticResource CVS}}" >
</GridView>
</Grid>
Best of luck.

- 5,705
- 2
- 45
- 58

- 31,313
- 14
- 117
- 233
-
Been looking for an answer to this all day - this is perfect, just what I needed. – Todd Main Oct 03 '13 at 02:23
-
@JerryNixon-MSFT Inside `Items_CollectionChanged` changed event, how would I handle __adding__ to the collection? Because currently __removing__ followed __adding__ would result in `HandleReorder()` – lbrahim Dec 04 '14 at 15:19
-
Since you can only add through code, you don't really need to listen to your collection, just expand your logic where you add the item. – Jerry Nixon Dec 05 '14 at 14:51
-
This is a nice approach on this topic but i have some questions regarding this. I use this to manipulate some GridViewItems and this method does work but i save the whole Collection from the ObservableCollection for later use and so the user does not load the items again and again. My problem is, the "CollectionChanged" event fires on each itemd added/removed, i would like to have a approach to trigger my method which saves the Collection to storage after all elements have been added/removed. is there a way? – dinchy87 Jan 30 '16 at 21:38
-