Jerry Nixon on Windows: Walkthrough: Reordering items in a GridView with Drag and Drop

Wednesday, June 12, 2013

Walkthrough: Reordering items in a GridView with Drag and Drop

imageSo, you have some data showing in a GridView. You have ordered it programmatically. Now, you want to let the user reorder it, manually, by dragging and dropping GridView items anywhere they want. Is it easy? It sure is.

GridView inherits from ListViewBase, which ultimately inherits from ItemsControl – the core repeater for the XAML framework. GridView is a horizontally-oriented data presenter that is, easily, the most common control used in Windows Store Apps on Windows 8. It gives a lot of functionality to developer right out-of-the-box. This includes grouping, selection, animations, and reordering.

MSDN: Use a GridView to display a collection of data that scrolls horizontally. To display a collection that scrolls vertically, use a ListView. GridView is an ItemsControl, so it can contain a collection of items of any type. To populate the view, add items to theItems collection, or set the ItemsSource property to a data source. By default, a data item is displayed in the GridView as the string representation of the data object it's bound to. To specify exactly how items in the GridView are displayed, you create a DataTemplate to define the layout of controls used to display an individual item.

GridView Basic Syntax

Two properties matter most on a GridView. ItemsSource and ItemTemplate. The ItemsSource property tells the GridView where the source data is, what data to repeat. The ItemTemplate tells the GridView how to display the data, the UI for each item.

image

In the above code, we enable drag and drop reordering of items in the simplest way. It’s nice and easy though not very practical insofar as a real app. Most of us want to use data from code-behind. Data from our cache, our web service, our database or something else. Here’s how we accomplish it:

image

In the code above we employ the core parts of a GridView necessary to reorder items in it. We identify a reusable DataTemplate, and bind the ItemSource to the View Model and property containing the source data. Let’s take a minute and walk through those 4 critical parts that allow reordering.

The 4 things you need

You need 4 things to get reordering working in the GridView. Of course, there are far more qualities to an app in the panoply of the XAML framework. But, these are the ones you must have in place – the ones specific to allow reordering:

  1. ObservableCollection: the System.Collections.ObjectModel.ObservableCollection<T> is perhaps the handiest generic list available to XAML developers. Its CollectionChanged event is part of the XAML framework allowing developers to manipulate the collection’s membership from code-behind and trust the resulting UI properly reflects the change. Moreover, ObservableCollection is a required ItemsSource value to enable GridView reordering.
  2. CanReorderItems: Gets or sets a value that indicates whether items in the view can be reordered through user interaction. True if items in the view can be reordered through user interaction; otherwise, false. The default is false.
  3. CanDragItems: Gets or sets a value that indicates whether items in the view can be dragged as data payload. True if items in the view can be dragged as data payload; otherwise, false. The default is false.
  4. AllowDrop: Gets or sets a value that determines whether this UIElement can be a drop target for purposes of drag-and-drop operations. true if this UIElement can be a drop target for purposes of drag-and-drop operations; otherwise, false. The default is false.

The CollectionViewSources,IsSourceGrouped property

Sometimes developers use a CollectionViewSource as an intermediary between their ItemsControl and the Collection. A CollectionViewSource enables both concurrency and grouping of data. But is NOT required for reordering data. Having said that, a CollectionViewSource CAN be used, but should its IsSourceGrouped property be set to true, reordering will no longer be enabled in the GridView.

Let’s see it work!

Is it just me or do I call the GridView a DataGrid over and over? :) It’s GridView.

In the video above, I walk through a simple grouping scenario with simple data. The code for this video includes the simple GridView syntax shown earlier in this article, as well as some simple ViewModel code, which I will provide here:

image

In the code above, I slap together a simple view model (for the XAML’s MVVM pattern). Specifically, I setup the ObservableCollection<T> property called Items which is read only. This read only approach to a property implies that only the internal logic of the view model is supposed to set the collection. We know, however, that because this is a collection, internal members of that collection (the records) can be manipulated by the consuming UI (the view) – in this case by reordering.

Understanding Reorder

There is no “Reorder” event, by the way. The GridView handles the Remove() of the dragged item from the ObservableCollection and the Insert() of the dropped item into the ObservableCollection. There is a CollectionChanged event with an Add and Remove action, but there is no Reorder event.

Should you need a Reorder event, you can infer one like this:

image

Understanding Drag and Drop

Though the Drag and Drop operations are encapsulated for you by the GridView, it’s worth understanding that the operations itself. For example, let’s change the parameters. We are not reordering inside a single GridView, we want to drag items between two GridViews. This operation requires only two events to be handled:

  1.  DragItemsStarting: This event occurs when you start a drag-and-drop operation, including when you perform a reorder operation by drag-and-drop. When you perform custom actions as a result of a drag-and-drop operation, you typically listen to this event and provide more data using the DragItemsStartingEventArgs.Data property.

    image
    In the code above, when the drag operation begins, we sniff the record being dragged (from the Items property in the event arguments) and save it into e.Data.Properties property bag which will later be shared with the event arguments of the drop event.
  2. Drop: This event occurs when the input system reports an underlying drop event with this element as the drop target. Drop is a routed event. An element must have AllowDrop be true to be a Drop event source. If the event is permitted to bubble up to parent elements because it goes unhandled, then it is possible to handle the event on a parent element if AllowDrop is true on the parent element. Intermediate elements in the route that aren't either the handler object or the drop target don't need AllowDrop to be true.

    image
    In the code above, we handle the drop event which is raised when the user has dropped a payload onto a target whose AllowDrop property is set to true. The first test is to ensure the correct objects are involved since drag/drop operations can occur on many different controls in your UI and may not be the ones you expect.

Conclusion

Many complex capabilities are encapsulated for you in the GridView. Specifically, reorder is there to help you provide rich functionality without a lot of work. With the simple steps at the beginning of this article your GridView can provide this. In addition, we discussed some advanced scenarios as well as some core concepts behind drag and drop.

Best of luck!